bitkeeper revision 1.1026.1.8 (40e1b09foCFBM0EuIgrSA1uLJrWuzA)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Tue, 29 Jun 2004 18:10:39 +0000 (18:10 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Tue, 29 Jun 2004 18:10:39 +0000 (18:10 +0000)
Restructuring the python code and libs - first stage.

256 files changed:
.rootkeys
BitKeeper/etc/ignore
tools/Make.defs [new file with mode: 0644]
tools/Makefile
tools/examples/Makefile
tools/examples/vifctl [new file with mode: 0644]
tools/examples/xm_dom_create.py [deleted file]
tools/lib/allocate.c [deleted file]
tools/lib/allocate.h [deleted file]
tools/lib/debug.h [deleted file]
tools/lib/enum.c [deleted file]
tools/lib/enum.h [deleted file]
tools/lib/file_stream.c [deleted file]
tools/lib/file_stream.h [deleted file]
tools/lib/gzip_stream.c [deleted file]
tools/lib/gzip_stream.h [deleted file]
tools/lib/hash_table.c [deleted file]
tools/lib/hash_table.h [deleted file]
tools/lib/iostream.c [deleted file]
tools/lib/iostream.h [deleted file]
tools/lib/kernel_stream.c [deleted file]
tools/lib/kernel_stream.h [deleted file]
tools/lib/lexis.c [deleted file]
tools/lib/lexis.h [deleted file]
tools/lib/lzi_stream.c [deleted file]
tools/lib/lzi_stream.h [deleted file]
tools/lib/lzo_stream.c [deleted file]
tools/lib/lzo_stream.h [deleted file]
tools/lib/marshal.c [deleted file]
tools/lib/marshal.h [deleted file]
tools/lib/socket_stream.c [deleted file]
tools/lib/socket_stream.h [deleted file]
tools/lib/string_stream.c [deleted file]
tools/lib/string_stream.h [deleted file]
tools/lib/sxpr.c [deleted file]
tools/lib/sxpr.h [deleted file]
tools/lib/sxpr_parser.c [deleted file]
tools/lib/sxpr_parser.h [deleted file]
tools/lib/sys_ctype.h [deleted file]
tools/lib/sys_net.c [deleted file]
tools/lib/sys_net.h [deleted file]
tools/lib/sys_string.c [deleted file]
tools/lib/sys_string.h [deleted file]
tools/lib/xdr.c [deleted file]
tools/lib/xdr.h [deleted file]
tools/libxc/Makefile [new file with mode: 0644]
tools/libxc/rpm.spec [new file with mode: 0644]
tools/libxc/xc.h [new file with mode: 0644]
tools/libxc/xc_atropos.c [new file with mode: 0644]
tools/libxc/xc_bvtsched.c [new file with mode: 0644]
tools/libxc/xc_domain.c [new file with mode: 0644]
tools/libxc/xc_elf.h [new file with mode: 0644]
tools/libxc/xc_evtchn.c [new file with mode: 0644]
tools/libxc/xc_io.c [new file with mode: 0644]
tools/libxc/xc_io.h [new file with mode: 0644]
tools/libxc/xc_linux_build.c [new file with mode: 0644]
tools/libxc/xc_linux_restore.c [new file with mode: 0644]
tools/libxc/xc_linux_save.c [new file with mode: 0644]
tools/libxc/xc_misc.c [new file with mode: 0644]
tools/libxc/xc_netbsd_build.c [new file with mode: 0644]
tools/libxc/xc_physdev.c [new file with mode: 0644]
tools/libxc/xc_private.c [new file with mode: 0644]
tools/libxc/xc_private.h [new file with mode: 0644]
tools/libxc/xc_rrobin.c [new file with mode: 0644]
tools/libxutil/Makefile [new file with mode: 0644]
tools/libxutil/allocate.c [new file with mode: 0644]
tools/libxutil/allocate.h [new file with mode: 0644]
tools/libxutil/debug.h [new file with mode: 0644]
tools/libxutil/enum.c [new file with mode: 0644]
tools/libxutil/enum.h [new file with mode: 0644]
tools/libxutil/file_stream.c [new file with mode: 0644]
tools/libxutil/file_stream.h [new file with mode: 0644]
tools/libxutil/gzip_stream.c [new file with mode: 0644]
tools/libxutil/gzip_stream.h [new file with mode: 0644]
tools/libxutil/hash_table.c [new file with mode: 0644]
tools/libxutil/hash_table.h [new file with mode: 0644]
tools/libxutil/iostream.c [new file with mode: 0644]
tools/libxutil/iostream.h [new file with mode: 0644]
tools/libxutil/kernel_stream.c [new file with mode: 0644]
tools/libxutil/kernel_stream.h [new file with mode: 0644]
tools/libxutil/lexis.c [new file with mode: 0644]
tools/libxutil/lexis.h [new file with mode: 0644]
tools/libxutil/lzi_stream.c [new file with mode: 0644]
tools/libxutil/lzi_stream.h [new file with mode: 0644]
tools/libxutil/lzo_stream.c [new file with mode: 0644]
tools/libxutil/lzo_stream.h [new file with mode: 0644]
tools/libxutil/marshal.c [new file with mode: 0644]
tools/libxutil/marshal.h [new file with mode: 0644]
tools/libxutil/socket_stream.c [new file with mode: 0644]
tools/libxutil/socket_stream.h [new file with mode: 0644]
tools/libxutil/string_stream.c [new file with mode: 0644]
tools/libxutil/string_stream.h [new file with mode: 0644]
tools/libxutil/sxpr.c [new file with mode: 0644]
tools/libxutil/sxpr.h [new file with mode: 0644]
tools/libxutil/sxpr_parser.c [new file with mode: 0644]
tools/libxutil/sxpr_parser.h [new file with mode: 0644]
tools/libxutil/sys_ctype.h [new file with mode: 0644]
tools/libxutil/sys_net.c [new file with mode: 0644]
tools/libxutil/sys_net.h [new file with mode: 0644]
tools/libxutil/sys_string.c [new file with mode: 0644]
tools/libxutil/sys_string.h [new file with mode: 0644]
tools/libxutil/xdr.c [new file with mode: 0644]
tools/libxutil/xdr.h [new file with mode: 0644]
tools/misc/Makefile
tools/misc/netfix
tools/misc/xend [new file with mode: 0644]
tools/misc/xm [new file with mode: 0755]
tools/python/Makefile [new file with mode: 0644]
tools/python/setup.py [new file with mode: 0644]
tools/python/xen/__init__.py [new file with mode: 0644]
tools/python/xen/ext/__init__.py [new file with mode: 0644]
tools/python/xen/ext/xc/Makefile [new file with mode: 0644]
tools/python/xen/ext/xc/setup.py [new file with mode: 0644]
tools/python/xen/ext/xc/xc.c [new file with mode: 0644]
tools/python/xen/ext/xu/__init__.py [new file with mode: 0644]
tools/python/xen/ext/xu/domain_controller.h [new file with mode: 0644]
tools/python/xen/ext/xu/xu.c [new file with mode: 0644]
tools/python/xen/util/Brctl.py [new file with mode: 0644]
tools/python/xen/util/__init__.py [new file with mode: 0644]
tools/python/xen/util/console_client.py [new file with mode: 0644]
tools/python/xen/util/ip.py [new file with mode: 0644]
tools/python/xen/util/tempfile.py [new file with mode: 0644]
tools/python/xen/xend/Args.py [new file with mode: 0644]
tools/python/xen/xend/EventServer.py [new file with mode: 0644]
tools/python/xen/xend/EventTypes.py [new file with mode: 0644]
tools/python/xen/xend/PrettyPrint.py [new file with mode: 0644]
tools/python/xen/xend/Vifctl.py [new file with mode: 0644]
tools/python/xen/xend/XendClient.py [new file with mode: 0644]
tools/python/xen/xend/XendConsole.py [new file with mode: 0644]
tools/python/xen/xend/XendDB.py [new file with mode: 0644]
tools/python/xen/xend/XendDomain.py [new file with mode: 0644]
tools/python/xen/xend/XendDomainConfig.py [new file with mode: 0644]
tools/python/xen/xend/XendDomainInfo.py [new file with mode: 0644]
tools/python/xen/xend/XendMigrate.py [new file with mode: 0644]
tools/python/xen/xend/XendNode.py [new file with mode: 0644]
tools/python/xen/xend/XendRoot.py [new file with mode: 0644]
tools/python/xen/xend/XendVnet.py [new file with mode: 0644]
tools/python/xen/xend/__init__.py [new file with mode: 0644]
tools/python/xen/xend/encode.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvBase.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvConsole.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvConsoleDir.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvDaemon.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvDeviceDir.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvDir.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvDomain.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvDomainDir.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvEventDir.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvNode.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvRoot.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvServer.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvVnetDir.py [new file with mode: 0644]
tools/python/xen/xend/server/__init__.py [new file with mode: 0644]
tools/python/xen/xend/server/blkif.py [new file with mode: 0755]
tools/python/xen/xend/server/channel.py [new file with mode: 0755]
tools/python/xen/xend/server/console.py [new file with mode: 0755]
tools/python/xen/xend/server/controller.py [new file with mode: 0755]
tools/python/xen/xend/server/cstruct.py [new file with mode: 0755]
tools/python/xen/xend/server/domain.py [new file with mode: 0644]
tools/python/xen/xend/server/messages.py [new file with mode: 0644]
tools/python/xen/xend/server/netif.py [new file with mode: 0755]
tools/python/xen/xend/server/params.py [new file with mode: 0644]
tools/python/xen/xend/sxp.py [new file with mode: 0644]
tools/python/xen/xm/__init__.py [new file with mode: 0644]
tools/python/xen/xm/create.py [new file with mode: 0644]
tools/python/xen/xm/main.py [new file with mode: 0644]
tools/python/xen/xm/opts.py [new file with mode: 0644]
tools/python/xen/xm/shutdown.py [new file with mode: 0644]
tools/xc/Makefile [deleted file]
tools/xc/lib/Makefile [deleted file]
tools/xc/lib/rpm.spec [deleted file]
tools/xc/lib/xc.h [deleted file]
tools/xc/lib/xc_atropos.c [deleted file]
tools/xc/lib/xc_bvtsched.c [deleted file]
tools/xc/lib/xc_domain.c [deleted file]
tools/xc/lib/xc_elf.h [deleted file]
tools/xc/lib/xc_evtchn.c [deleted file]
tools/xc/lib/xc_io.c [deleted file]
tools/xc/lib/xc_io.h [deleted file]
tools/xc/lib/xc_linux_build.c [deleted file]
tools/xc/lib/xc_linux_restore.c [deleted file]
tools/xc/lib/xc_linux_save.c [deleted file]
tools/xc/lib/xc_misc.c [deleted file]
tools/xc/lib/xc_netbsd_build.c [deleted file]
tools/xc/lib/xc_physdev.c [deleted file]
tools/xc/lib/xc_private.c [deleted file]
tools/xc/lib/xc_private.h [deleted file]
tools/xc/lib/xc_rrobin.c [deleted file]
tools/xc/py/Makefile [deleted file]
tools/xc/py/Xc.c [deleted file]
tools/xc/py/setup.py [deleted file]
tools/xen/Makefile [deleted file]
tools/xen/lib/__init__.py [deleted file]
tools/xen/lib/ext/__init__.py [deleted file]
tools/xen/lib/util/Brctl.py [deleted file]
tools/xen/lib/util/__init__.py [deleted file]
tools/xen/lib/util/console_client.py [deleted file]
tools/xen/lib/util/ip.py [deleted file]
tools/xen/lib/util/tempfile.py [deleted file]
tools/xen/lib/xend/Args.py [deleted file]
tools/xen/lib/xend/EventServer.py [deleted file]
tools/xen/lib/xend/EventTypes.py [deleted file]
tools/xen/lib/xend/PrettyPrint.py [deleted file]
tools/xen/lib/xend/Vifctl.py [deleted file]
tools/xen/lib/xend/XendClient.py [deleted file]
tools/xen/lib/xend/XendConsole.py [deleted file]
tools/xen/lib/xend/XendDB.py [deleted file]
tools/xen/lib/xend/XendDomain.py [deleted file]
tools/xen/lib/xend/XendDomainConfig.py [deleted file]
tools/xen/lib/xend/XendDomainInfo.py [deleted file]
tools/xen/lib/xend/XendMigrate.py [deleted file]
tools/xen/lib/xend/XendNode.py [deleted file]
tools/xen/lib/xend/XendRoot.py [deleted file]
tools/xen/lib/xend/XendVnet.py [deleted file]
tools/xen/lib/xend/__init__.py [deleted file]
tools/xen/lib/xend/encode.py [deleted file]
tools/xen/lib/xend/server/SrvBase.py [deleted file]
tools/xen/lib/xend/server/SrvConsole.py [deleted file]
tools/xen/lib/xend/server/SrvConsoleDir.py [deleted file]
tools/xen/lib/xend/server/SrvDaemon.py [deleted file]
tools/xen/lib/xend/server/SrvDeviceDir.py [deleted file]
tools/xen/lib/xend/server/SrvDir.py [deleted file]
tools/xen/lib/xend/server/SrvDomain.py [deleted file]
tools/xen/lib/xend/server/SrvDomainDir.py [deleted file]
tools/xen/lib/xend/server/SrvEventDir.py [deleted file]
tools/xen/lib/xend/server/SrvNode.py [deleted file]
tools/xen/lib/xend/server/SrvRoot.py [deleted file]
tools/xen/lib/xend/server/SrvServer.py [deleted file]
tools/xen/lib/xend/server/SrvVnetDir.py [deleted file]
tools/xen/lib/xend/server/__init__.py [deleted file]
tools/xen/lib/xend/server/blkif.py [deleted file]
tools/xen/lib/xend/server/channel.py [deleted file]
tools/xen/lib/xend/server/console.py [deleted file]
tools/xen/lib/xend/server/controller.py [deleted file]
tools/xen/lib/xend/server/cstruct.py [deleted file]
tools/xen/lib/xend/server/domain.py [deleted file]
tools/xen/lib/xend/server/messages.py [deleted file]
tools/xen/lib/xend/server/netif.py [deleted file]
tools/xen/lib/xend/server/params.py [deleted file]
tools/xen/lib/xend/sxp.py [deleted file]
tools/xen/lib/xm/__init__.py [deleted file]
tools/xen/lib/xm/create.py [deleted file]
tools/xen/lib/xm/main.py [deleted file]
tools/xen/lib/xm/opts.py [deleted file]
tools/xen/lib/xm/shutdown.py [deleted file]
tools/xen/setup.py [deleted file]
tools/xen/vifctl [deleted file]
tools/xen/xend [deleted file]
tools/xen/xm [deleted file]
tools/xentrace/Makefile
tools/xentrace/xentrace.c
tools/xu/Makefile [deleted file]
tools/xu/lib/__init__.py [deleted file]
tools/xu/lib/domain_controller.h [deleted file]
tools/xu/lib/xu.c [deleted file]
tools/xu/setup.py [deleted file]

index a901a1d4cd46c580f2f8c0923222346205671679..4bff522d3332c42aace546dcc328ac0904d4a7c8 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3e5a4e681xMPdF9xCMwpyfuYMySU5g linux-2.4.26-xen-sparse/mm/mremap.c
 409ba2e7akOFqQUg6Qyg2s28xcXiMg linux-2.4.26-xen-sparse/mm/page_alloc.c
 3e5a4e683HKVU-sxtagrDasRB8eBVw linux-2.4.26-xen-sparse/mm/swapfile.c
+40e1b09db5mN69Ijj0X_Eol-S7dXiw tools/Make.defs
 3f776bd1Hy9rn69ntXBhPReUFw9IEA tools/Makefile
 401d7e160vaxMBAUSLSicuZ7AQjJ3w tools/examples/Makefile
 401d7e16UgeqroJQTIhwkrDVkoWgZQ tools/examples/README
 405ff55dawQyCHFEnJ067ChPRoXBBA tools/examples/init.d/xend
 40278d94cIUWl2eRgnwZtr4hTyWT1Q tools/examples/init.d/xendomains
 40278d91ZjLhxdjjrGe8HEdwHLj5xQ tools/examples/netbsd
+40e15b7edWEtBf_oe3eBwGKuh1dyzQ tools/examples/vifctl
 401d7e16NpnVrFSsR7lKKKfTwCYvWA tools/examples/xc_dom_control.py
 401d7e16RJj-lbtsVEjua6HYAIiKiA tools/examples/xc_dom_create.py
-40c9c468pXANclL7slGaoD0kSrIwoQ tools/examples/xm_dom_create.py
 40cf2937oKlROYOJTN8GWwWM5AmjBg tools/examples/xmdefaults
 40dfd40auJwNnb8NoiSnRkvZaaXkUg tools/examples/xmnetbsd
-40e033325Sjqs-_4TuzeUEprP_gYFg tools/lib/allocate.c
-40e03332KYz7o1bn2MG_KPbBlyoIMA tools/lib/allocate.h
-40e03332IyRttYoXKoJla5qCC514SQ tools/lib/debug.h
-40e03332qV5tJ-GJZjo-LBCeGuEjJA tools/lib/enum.c
-40e03332wwMVxfobgA1PSMTSAGLiCw tools/lib/enum.h
-40e03332p5Dc_owJQRuN72ymJZddFQ tools/lib/file_stream.c
-40e03332jWfB2viAhLSkq1WK0r_iDQ tools/lib/file_stream.h
-40e03332rUjNMGg11n2rN6V4DCrvOg tools/lib/gzip_stream.c
-40e033321O5Qg22haLoq5lpmk4tooQ tools/lib/gzip_stream.h
-40e03332QrTR96tc6yS2rMBpd2mq1A tools/lib/hash_table.c
-40e033325KoIb0d_uy8s7b5DUR9fPQ tools/lib/hash_table.h
-40e03332ihnBGzHykVwZnFmkAppb4g tools/lib/iostream.c
-40e03332UGwbLR4wsw4ft14p0Yw5pg tools/lib/iostream.h
-40e0333245DLDzJemeSVBLuutHtzEQ tools/lib/kernel_stream.c
-40e03332aK0GkgpDdc-PVTkWKTeOBg tools/lib/kernel_stream.h
-40e03332HJ0cDcZDKDUUT-tEiBWOZw tools/lib/lexis.c
-40e03332tnH9Ggzxbfi3xY9Vh2hUlg tools/lib/lexis.h
-40e03332aYIW0BNBh6wXuKKn_P7Yyg tools/lib/lzi_stream.c
-40e0333233voTffE4cJSMGJARfiSSQ tools/lib/lzi_stream.h
-40e03332FXuMoUnfsAKSgV8X4rFbYQ tools/lib/lzo_stream.c
-40e03332InJaiLfpDcIXBy2fI0RFGQ tools/lib/lzo_stream.h
-40e03332a5SCuRsejHStTuWzMQNv8Q tools/lib/marshal.c
-40e03332TwKyJrZQiiQfNq4vc2hpgw tools/lib/marshal.h
-40e033328ccHlJuTR1FswYL_EC6LFA tools/lib/socket_stream.c
-40e03332P0KVQGkmahj47aafo1X0nA tools/lib/socket_stream.h
-40e03332KT_tnnoAMbPVAZBB7kSOAQ tools/lib/string_stream.c
-40e03332-VtK6_OZa1vMHXFil8uq6w tools/lib/string_stream.h
-40e03332dDtczi6YX7_mMxhYjJeAdQ tools/lib/sxpr.c
-40e03332QPuyNKDOTIYVvkwK5qO-vg tools/lib/sxpr.h
-40e03332Pi0_osJ3XPBi38ADPqdl4A tools/lib/sxpr_parser.c
-40e033324v5QFMvWEXXzv38uUT9kHg tools/lib/sxpr_parser.h
-40e03332gKUInsqtxQOV4mPiMqf_dg tools/lib/sys_ctype.h
-40e03332Rkvq6nn_UNjzAAK_Tk9v1g tools/lib/sys_net.c
-40e03332lQHvQHw4Rh7VsT1_sui29A tools/lib/sys_net.h
-40e033321smklZd7bDSdWvQCeIshtg tools/lib/sys_string.c
-40e03332h5V611rRWURRLqb1Ekatxg tools/lib/sys_string.h
-40e03332u4q5kgF0N7RfqB4s0pZVew tools/lib/xdr.c
-40e03332hY16nfRXF4gGd5S1aUJUBw tools/lib/xdr.h
+3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/libxc/Makefile
+3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/libxc/rpm.spec
+3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/libxc/xc.h
+40589968oCfoUlXd460CjVAkBE8IBA tools/libxc/xc_atropos.c
+3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/libxc/xc_bvtsched.c
+3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/libxc/xc_domain.c
+40278d99BLsfUv3qxv0I8C1sClZ0ow tools/libxc/xc_elf.h
+403e0977Bjsm_e82pwvl9VvaJxh8Gg tools/libxc/xc_evtchn.c
+40e03333Eegw8czSWvHsbKxrRZJjRA tools/libxc/xc_io.c
+40e03333vrWGbLAhyJjXlqCHaJt7eA tools/libxc/xc_io.h
+3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/libxc/xc_linux_build.c
+3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/libxc/xc_linux_restore.c
+3fbba6db7li3FJiABYtCmuGxOJxEGw tools/libxc/xc_linux_save.c
+3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/libxc/xc_misc.c
+40278d9ctaHVDaEuwhXI3Om2JOjx9w tools/libxc/xc_netbsd_build.c
+4051bce6CHAsYh8P5t2OHDtRWOP9og tools/libxc/xc_physdev.c
+3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/libxc/xc_private.c
+3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/libxc/xc_private.h
+40589968UQFnJeOMn8UIFLbXBuwXjw tools/libxc/xc_rrobin.c
+40e1b09dMYB4ItGCqcMIzirdMd9I-w tools/libxutil/Makefile
+40e033325Sjqs-_4TuzeUEprP_gYFg tools/libxutil/allocate.c
+40e03332KYz7o1bn2MG_KPbBlyoIMA tools/libxutil/allocate.h
+40e03332IyRttYoXKoJla5qCC514SQ tools/libxutil/debug.h
+40e03332qV5tJ-GJZjo-LBCeGuEjJA tools/libxutil/enum.c
+40e03332wwMVxfobgA1PSMTSAGLiCw tools/libxutil/enum.h
+40e03332p5Dc_owJQRuN72ymJZddFQ tools/libxutil/file_stream.c
+40e03332jWfB2viAhLSkq1WK0r_iDQ tools/libxutil/file_stream.h
+40e03332rUjNMGg11n2rN6V4DCrvOg tools/libxutil/gzip_stream.c
+40e033321O5Qg22haLoq5lpmk4tooQ tools/libxutil/gzip_stream.h
+40e03332QrTR96tc6yS2rMBpd2mq1A tools/libxutil/hash_table.c
+40e033325KoIb0d_uy8s7b5DUR9fPQ tools/libxutil/hash_table.h
+40e03332ihnBGzHykVwZnFmkAppb4g tools/libxutil/iostream.c
+40e03332UGwbLR4wsw4ft14p0Yw5pg tools/libxutil/iostream.h
+40e0333245DLDzJemeSVBLuutHtzEQ tools/libxutil/kernel_stream.c
+40e03332aK0GkgpDdc-PVTkWKTeOBg tools/libxutil/kernel_stream.h
+40e03332HJ0cDcZDKDUUT-tEiBWOZw tools/libxutil/lexis.c
+40e03332tnH9Ggzxbfi3xY9Vh2hUlg tools/libxutil/lexis.h
+40e03332aYIW0BNBh6wXuKKn_P7Yyg tools/libxutil/lzi_stream.c
+40e0333233voTffE4cJSMGJARfiSSQ tools/libxutil/lzi_stream.h
+40e03332FXuMoUnfsAKSgV8X4rFbYQ tools/libxutil/lzo_stream.c
+40e03332InJaiLfpDcIXBy2fI0RFGQ tools/libxutil/lzo_stream.h
+40e03332a5SCuRsejHStTuWzMQNv8Q tools/libxutil/marshal.c
+40e03332TwKyJrZQiiQfNq4vc2hpgw tools/libxutil/marshal.h
+40e033328ccHlJuTR1FswYL_EC6LFA tools/libxutil/socket_stream.c
+40e03332P0KVQGkmahj47aafo1X0nA tools/libxutil/socket_stream.h
+40e03332KT_tnnoAMbPVAZBB7kSOAQ tools/libxutil/string_stream.c
+40e03332-VtK6_OZa1vMHXFil8uq6w tools/libxutil/string_stream.h
+40e03332dDtczi6YX7_mMxhYjJeAdQ tools/libxutil/sxpr.c
+40e03332QPuyNKDOTIYVvkwK5qO-vg tools/libxutil/sxpr.h
+40e03332Pi0_osJ3XPBi38ADPqdl4A tools/libxutil/sxpr_parser.c
+40e033324v5QFMvWEXXzv38uUT9kHg tools/libxutil/sxpr_parser.h
+40e03332gKUInsqtxQOV4mPiMqf_dg tools/libxutil/sys_ctype.h
+40e03332Rkvq6nn_UNjzAAK_Tk9v1g tools/libxutil/sys_net.c
+40e03332lQHvQHw4Rh7VsT1_sui29A tools/libxutil/sys_net.h
+40e033321smklZd7bDSdWvQCeIshtg tools/libxutil/sys_string.c
+40e03332h5V611rRWURRLqb1Ekatxg tools/libxutil/sys_string.h
+40e03332u4q5kgF0N7RfqB4s0pZVew tools/libxutil/xdr.c
+40e03332hY16nfRXF4gGd5S1aUJUBw tools/libxutil/xdr.h
 3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
 40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen
 3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
 3f5ef5a2dTZP0nnsFoeq2jRf3mWDDg tools/misc/xen-clone.README
 3f870808zS6T6iFhqYPGelroZlVfGQ tools/misc/xen_cpuperf.c
 405eedf6_nnNhFQ1I85lhCkLK6jFGA tools/misc/xencons
+40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/misc/xend
 4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops.py
-3fbca441SjQr8vJwTQIgH1laysaWog tools/xc/Makefile
-3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/xc/lib/Makefile
-3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/xc/lib/rpm.spec
-3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/xc/lib/xc.h
-40589968oCfoUlXd460CjVAkBE8IBA tools/xc/lib/xc_atropos.c
-3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/xc/lib/xc_bvtsched.c
-3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/xc/lib/xc_domain.c
-40278d99BLsfUv3qxv0I8C1sClZ0ow tools/xc/lib/xc_elf.h
-403e0977Bjsm_e82pwvl9VvaJxh8Gg tools/xc/lib/xc_evtchn.c
-40e03333Eegw8czSWvHsbKxrRZJjRA tools/xc/lib/xc_io.c
-40e03333vrWGbLAhyJjXlqCHaJt7eA tools/xc/lib/xc_io.h
-3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/xc/lib/xc_linux_build.c
-3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/xc/lib/xc_linux_restore.c
-3fbba6db7li3FJiABYtCmuGxOJxEGw tools/xc/lib/xc_linux_save.c
-3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/xc/lib/xc_misc.c
-40278d9ctaHVDaEuwhXI3Om2JOjx9w tools/xc/lib/xc_netbsd_build.c
-4051bce6CHAsYh8P5t2OHDtRWOP9og tools/xc/lib/xc_physdev.c
-3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/xc/lib/xc_private.c
-3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/xc/lib/xc_private.h
-40589968UQFnJeOMn8UIFLbXBuwXjw tools/xc/lib/xc_rrobin.c
-3fbd0a3dTwnDcfdw0-v46dPbX98zDw tools/xc/py/Makefile
-3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/xc/py/Xc.c
-3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/xc/py/setup.py
-40c9c468icGyC5RAF1bRKsCXPDCvsA tools/xen/Makefile
-40dc4076hGpwa8-sWRN0jtXZeQJuKg tools/xen/lib/__init__.py
-40dfd40aMOhnw_cQLve9462UR5yYxQ tools/xen/lib/ext/__init__.py
-40d8915cyoVA0hJxiBFNymL7YvDaRg tools/xen/lib/util/Brctl.py
-40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/xen/lib/util/__init__.py
-4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xen/lib/util/console_client.py
-40c9c468IienauFHQ_xJIcqnPJ8giQ tools/xen/lib/util/ip.py
-4059c6a0pnxhG8hwSOivXybbGOwuXw tools/xen/lib/util/tempfile.py
-40c9c468SNuObE_YWARyS0hzTPSzKg tools/xen/lib/xend/Args.py
-40c9c468Um_qc66OQeLEceIz1pgD5g tools/xen/lib/xend/EventServer.py
-40c9c468U8EVl0d3G--8YXVg6VJD3g tools/xen/lib/xend/EventTypes.py
-40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/xen/lib/xend/PrettyPrint.py
-40e15b7eeQxWE_hUPB2YTgM9fsZ1PQ tools/xen/lib/xend/Vifctl.py
-40c9c4688m3eqnC8fhLu1APm36VOVA tools/xen/lib/xend/XendClient.py
-40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/xen/lib/xend/XendConsole.py
-40c9c468WnXs6eOUSff23IIGI4kMfQ tools/xen/lib/xend/XendDB.py
-40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/xen/lib/xend/XendDomain.py
-40c9c468bbKq3uC7_fuNUkiMMjArdw tools/xen/lib/xend/XendDomainConfig.py
-40c9c4685ykq87_n1kVUbMr9flx9fg tools/xen/lib/xend/XendDomainInfo.py
-40c9c46854nsHmuxHQHncKk5rAs5NA tools/xen/lib/xend/XendMigrate.py
-40c9c468M96gA1EYDvNa5w5kQNYLFA tools/xen/lib/xend/XendNode.py
-40c9c4686jruMyZIqiaZRMiMoqMJtg tools/xen/lib/xend/XendRoot.py
-40c9c468xzANp6o2D_MeCYwNmOIUsQ tools/xen/lib/xend/XendVnet.py
-40c9c468x191zetrVlMnExfsQWHxIQ tools/xen/lib/xend/__init__.py
-40c9c468S2YnCEKmk4ey8XQIST7INg tools/xen/lib/xend/encode.py
-40c9c468DCpMe542varOolW1Xc68ew tools/xen/lib/xend/server/SrvBase.py
-40c9c468IxQabrKJSWs0aEjl-27mRQ tools/xen/lib/xend/server/SrvConsole.py
-40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/xen/lib/xend/server/SrvConsoleDir.py
-40c9c468woSmBByfeXA4o_jGf2gCgA tools/xen/lib/xend/server/SrvDaemon.py
-40c9c468kACsmkqjxBWKHRo071L26w tools/xen/lib/xend/server/SrvDeviceDir.py
-40c9c468EQZJVkCLds-OhesJVVyZbQ tools/xen/lib/xend/server/SrvDir.py
-40c9c468TyHZUq8sk0FF_vxM6Sozrg tools/xen/lib/xend/server/SrvDomain.py
-40c9c469WzajDjutou3X7FmL9hMf3g tools/xen/lib/xend/server/SrvDomainDir.py
-40c9c469-8mYEJJTAR6w_ClrJRAfwQ tools/xen/lib/xend/server/SrvEventDir.py
-40c9c4694eu5759Dehr4Uhakei0EMg tools/xen/lib/xend/server/SrvNode.py
-40c9c469TaZ83ypsrktmPSHLEZiP5w tools/xen/lib/xend/server/SrvRoot.py
-40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/xen/lib/xend/server/SrvServer.py
-40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/xen/lib/xend/server/SrvVnetDir.py
-40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/xen/lib/xend/server/__init__.py
-40c9c4692hckPol_EK0EGB16ZyDsyQ tools/xen/lib/xend/server/blkif.py
-40c9c469N2-b3GqpLHHHPZykJPLVvA tools/xen/lib/xend/server/channel.py
-40c9c469hJ_IlatRne-9QEa0-wlquw tools/xen/lib/xend/server/console.py
-40c9c469UcNJh_NuLU0ytorM0Lk5Ow tools/xen/lib/xend/server/controller.py
-40c9c469vHh-qLiiubdbKEQbJf18Zw tools/xen/lib/xend/server/cstruct.py
-40d83983OXjt-y3HjSCcuoPp9rzvmw tools/xen/lib/xend/server/domain.py
-40c9c469yrm31i60pGKslTi2Zgpotg tools/xen/lib/xend/server/messages.py
-40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/xen/lib/xend/server/netif.py
-40c9c469ZqILEQ8x6yWy0_51jopiCg tools/xen/lib/xend/server/params.py
-40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/xen/lib/xend/sxp.py
-40d05079aFRp6NQdo5wIh5Ly31c0cg tools/xen/lib/xm/__init__.py
-40cf2937gKQcATgXKGtNeWb1PDH5nA tools/xen/lib/xm/create.py
-40cf2937isyS250zyd0Q2GuEDoNXfQ tools/xen/lib/xm/main.py
-40cf2937PSslwBliN1g7ofDy2H_RhA tools/xen/lib/xm/opts.py
-40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/xen/lib/xm/shutdown.py
-40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/xen/setup.py
-40e15b7edWEtBf_oe3eBwGKuh1dyzQ tools/xen/vifctl
-40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/xen/xend
-40cf2937dqM1jWW87O5OoOYND8leuA tools/xen/xm
+40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
+40c9c468icGyC5RAF1bRKsCXPDCvsA tools/python/Makefile
+40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/python/setup.py
+40dc4076hGpwa8-sWRN0jtXZeQJuKg tools/python/xen/__init__.py
+40dfd40aMOhnw_cQLve9462UR5yYxQ tools/python/xen/ext/__init__.py
+3fbd0a3dTwnDcfdw0-v46dPbX98zDw tools/python/xen/ext/xc/Makefile
+3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/python/xen/ext/xc/setup.py
+3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/python/xen/ext/xc/xc.c
+40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/python/xen/ext/xu/__init__.py
+40dc4076pVeE1kEEWzcUaNZin65kCA tools/python/xen/ext/xu/domain_controller.h
+40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/python/xen/ext/xu/xu.c
+40d8915cyoVA0hJxiBFNymL7YvDaRg tools/python/xen/util/Brctl.py
+40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/python/xen/util/__init__.py
+4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/python/xen/util/console_client.py
+40c9c468IienauFHQ_xJIcqnPJ8giQ tools/python/xen/util/ip.py
+4059c6a0pnxhG8hwSOivXybbGOwuXw tools/python/xen/util/tempfile.py
+40c9c468SNuObE_YWARyS0hzTPSzKg tools/python/xen/xend/Args.py
+40c9c468Um_qc66OQeLEceIz1pgD5g tools/python/xen/xend/EventServer.py
+40c9c468U8EVl0d3G--8YXVg6VJD3g tools/python/xen/xend/EventTypes.py
+40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/python/xen/xend/PrettyPrint.py
+40e15b7eeQxWE_hUPB2YTgM9fsZ1PQ tools/python/xen/xend/Vifctl.py
+40c9c4688m3eqnC8fhLu1APm36VOVA tools/python/xen/xend/XendClient.py
+40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/python/xen/xend/XendConsole.py
+40c9c468WnXs6eOUSff23IIGI4kMfQ tools/python/xen/xend/XendDB.py
+40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/python/xen/xend/XendDomain.py
+40c9c468bbKq3uC7_fuNUkiMMjArdw tools/python/xen/xend/XendDomainConfig.py
+40c9c4685ykq87_n1kVUbMr9flx9fg tools/python/xen/xend/XendDomainInfo.py
+40c9c46854nsHmuxHQHncKk5rAs5NA tools/python/xen/xend/XendMigrate.py
+40c9c468M96gA1EYDvNa5w5kQNYLFA tools/python/xen/xend/XendNode.py
+40c9c4686jruMyZIqiaZRMiMoqMJtg tools/python/xen/xend/XendRoot.py
+40c9c468xzANp6o2D_MeCYwNmOIUsQ tools/python/xen/xend/XendVnet.py
+40c9c468x191zetrVlMnExfsQWHxIQ tools/python/xen/xend/__init__.py
+40c9c468S2YnCEKmk4ey8XQIST7INg tools/python/xen/xend/encode.py
+40c9c468DCpMe542varOolW1Xc68ew tools/python/xen/xend/server/SrvBase.py
+40c9c468IxQabrKJSWs0aEjl-27mRQ tools/python/xen/xend/server/SrvConsole.py
+40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/python/xen/xend/server/SrvConsoleDir.py
+40c9c468woSmBByfeXA4o_jGf2gCgA tools/python/xen/xend/server/SrvDaemon.py
+40c9c468kACsmkqjxBWKHRo071L26w tools/python/xen/xend/server/SrvDeviceDir.py
+40c9c468EQZJVkCLds-OhesJVVyZbQ tools/python/xen/xend/server/SrvDir.py
+40c9c468TyHZUq8sk0FF_vxM6Sozrg tools/python/xen/xend/server/SrvDomain.py
+40c9c469WzajDjutou3X7FmL9hMf3g tools/python/xen/xend/server/SrvDomainDir.py
+40c9c469-8mYEJJTAR6w_ClrJRAfwQ tools/python/xen/xend/server/SrvEventDir.py
+40c9c4694eu5759Dehr4Uhakei0EMg tools/python/xen/xend/server/SrvNode.py
+40c9c469TaZ83ypsrktmPSHLEZiP5w tools/python/xen/xend/server/SrvRoot.py
+40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/python/xen/xend/server/SrvServer.py
+40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/python/xen/xend/server/SrvVnetDir.py
+40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/python/xen/xend/server/__init__.py
+40c9c4692hckPol_EK0EGB16ZyDsyQ tools/python/xen/xend/server/blkif.py
+40c9c469N2-b3GqpLHHHPZykJPLVvA tools/python/xen/xend/server/channel.py
+40c9c469hJ_IlatRne-9QEa0-wlquw tools/python/xen/xend/server/console.py
+40c9c469UcNJh_NuLU0ytorM0Lk5Ow tools/python/xen/xend/server/controller.py
+40c9c469vHh-qLiiubdbKEQbJf18Zw tools/python/xen/xend/server/cstruct.py
+40d83983OXjt-y3HjSCcuoPp9rzvmw tools/python/xen/xend/server/domain.py
+40c9c469yrm31i60pGKslTi2Zgpotg tools/python/xen/xend/server/messages.py
+40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/python/xen/xend/server/netif.py
+40c9c469ZqILEQ8x6yWy0_51jopiCg tools/python/xen/xend/server/params.py
+40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/python/xen/xend/sxp.py
+40d05079aFRp6NQdo5wIh5Ly31c0cg tools/python/xen/xm/__init__.py
+40cf2937gKQcATgXKGtNeWb1PDH5nA tools/python/xen/xm/create.py
+40cf2937isyS250zyd0Q2GuEDoNXfQ tools/python/xen/xm/main.py
+40cf2937PSslwBliN1g7ofDy2H_RhA tools/python/xen/xm/opts.py
+40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/python/xen/xm/shutdown.py
 403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
 40a107afN60pFdURgBv9KwEzgRl5mQ tools/xentrace/formats
 4050c413PhhLNAYk3TEwP37i_iLw9Q tools/xentrace/xentrace.8
 403a3edbVpV2E_wq1zeEkJ_n4Uu2eg tools/xentrace/xentrace.c
 403a3edblCUrzSj0mmKhO5HOPrOrSQ tools/xentrace/xentrace_format
 4050c413NtuyIq5lsYJV4P7KIjujXw tools/xentrace/xentrace_format.1
-40dfd40a0QtsSGigB9TCpVGWZmhlNA tools/xu/Makefile
-40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/xu/lib/__init__.py
-40dc4076pVeE1kEEWzcUaNZin65kCA tools/xu/lib/domain_controller.h
-40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/xu/lib/xu.c
-40dc4076FyWUYS2nX9YufgglUzKX2A tools/xu/setup.py
 3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING
 3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile
 3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen/Rules.mk
index 6f52b7f4ec8604216e8fd9bb601f8163af73ee71..a45244fe007b621eaefb044c59a6ccedab295997 100644 (file)
@@ -53,3 +53,22 @@ xen/xen
 xen/xen-syms
 xen/xen.*
 tools/xc/lib/.xc_rrobin.o.d
+tools/libxc/.xc_atropos.o.d
+tools/libxc/.xc_bvtsched.o.d
+tools/libxc/.xc_domain.o.d
+tools/libxc/.xc_evtchn.o.d
+tools/libxc/.xc_io.o.d
+tools/libxc/.xc_linux_build.o.d
+tools/libxc/.xc_linux_restore.o.d
+tools/libxc/.xc_linux_save.o.d
+tools/libxc/.xc_misc.o.d
+tools/libxc/.xc_netbsd_build.o.d
+tools/libxc/.xc_physdev.o.d
+tools/libxc/.xc_private.o.d
+tools/libxc/.xc_rrobin.o.d
+tools/libxutil/.allocate.o.d
+tools/libxutil/.file_stream.o.d
+tools/libxutil/.gzip_stream.o.d
+tools/libxutil/.iostream.o.d
+tools/libxutil/.sys_net.o.d
+tools/libxutil/.sys_string.o.d
diff --git a/tools/Make.defs b/tools/Make.defs
new file mode 100644 (file)
index 0000000..051baef
--- /dev/null
@@ -0,0 +1,7 @@
+#  -*- mode: Makefile; -*-
+XEN_HYPERVISOR_IFS = $(XEN_ROOT)/xen/include/hypervisor-ifs
+XEN_LINUX_INCLUDE  = $(XEN_ROOT)/linux-xen-sparse/include
+XEN_XU             = $(XEN_ROOT)/tools/python/xen/ext/xu
+XEN_XC             = $(XEN_ROOT)/tools/python/xen/ext/xc
+XEN_LIBXC          = $(XEN_ROOT)/tools/libxc
+XEN_LIBXUTIL       = $(XEN_ROOT)/tools/libxutil
index 908f49b682fb624131e9b56fd8abc4410a8850d0..b366034eb28b0cf754a85db1a5e2d0ca09dbd64b 100644 (file)
@@ -1,29 +1,29 @@
 
 all:   
-       $(MAKE) -C xc
-       $(MAKE) -C xu
+       $(MAKE) -C libxutil
+       $(MAKE) -C libxc
        $(MAKE) -C misc
        $(MAKE) -C examples
        $(MAKE) -C xentrace
-       $(MAKE) -C xen
+       $(MAKE) -C python
 
 install: all
-       $(MAKE) -C xc install
-       $(MAKE) -C xu install
+       $(MAKE) -C libxutil install
+       $(MAKE) -C libxc install
        $(MAKE) -C misc install
        $(MAKE) -C examples install
        $(MAKE) -C xentrace install
-       $(MAKE) -C xen install
+       $(MAKE) -C python install
 
 dist: $(TARGET)
        $(MAKE) prefix=`pwd`/../../install dist=yes install
 
 
 clean:
-       $(MAKE) -C xc clean
-       $(MAKE) -C xu clean
+       $(MAKE) -C libxutil clean
+       $(MAKE) -C libxc clean
        $(MAKE) -C misc clean
        $(MAKE) -C examples clean
        $(MAKE) -C xentrace clean
-       $(MAKE) -C xen clean
+       $(MAKE) -C python clean
 
index 3f7075ed1dc0bc727f8c9ae2d7ca3df558bad00a..794933d5d63d12c84d7eaacc950cfc833d351637 100644 (file)
@@ -1,21 +1,40 @@
 
 INSTALL  = $(wildcard *.py)
+
 ETC     = defaults democd netbsd xmdefaults
 ETCDIR   = /etc/xen
+
 INITD    = init.d/xendomains init.d/xend
 
+XEND     = vifctl
+XEND_DIR = $(ETCDIR)/xend
+
 all: 
 
-install: all
+install: all install-bin install-initd install-etc install-xend
+
+install-bin:
        mkdir -p $(prefix)/usr/bin
+       install -m0755 $(INSTALL) $(prefix)/usr/bin
+
+install-initd:
+       mkdir -p $(prefix)/etc/init.d
+       install -m0755 $(INITD) $(prefix)/etc/init.d
+
+install-etc:
        mkdir -p $(prefix)$(ETCDIR)
        mkdir -p $(prefix)$(ETCDIR)/auto
-       mkdir -p $(prefix)/etc/init.d
-       install -m0755 $(INSTALL) $(prefix)/usr/bin
        for i in $(ETC); \
            do [ -a $(prefix)/$(ETCDIR)/$$i ] || \
            install -m0644 $$i $(prefix)$(ETCDIR); \
        done
-       install -m0755 $(INITD) $(prefix)/etc/init.d
+
+install-xend:
+       mkdir -p $(prefix)$(XEND_DIR)
+       for i in $(XEND); \
+           do [ -a $(prefix)/$(XEND_DIR)/$$i ] || \
+           install -m0755 $$i $(prefix)$(XEND_DIR); \
+       done
+
 
 clean:
diff --git a/tools/examples/vifctl b/tools/examples/vifctl
new file mode 100644 (file)
index 0000000..d71459e
--- /dev/null
@@ -0,0 +1,149 @@
+#!/usr/bin/python
+#  -*- mode: python; -*-
+#============================================================================
+# Xen vif control script. Lives in /etc/xen/xend.
+#
+# vifctl init [bridge=<bridge>] [interface=<interface>]
+#
+#    Called when xend starts up. Default behaviour is to create <bridge>
+#    and add <interface> to it, moving its IP address to <bridge> and adjusting routes.
+#
+# vifctl (up|down) vif=<vif> mac=<mac> [bridge=<bridge>] (ipaddr=<ipaddr>)*
+#
+#    Called when a vif is brought up or down. Default behaviour is to add
+#    the vif to <bridge> on up and remove it from the bridge on down.
+#    If ipaddr is specified, iptables rules for the ip addresses are
+#    added on up and removed on down. The bridge a vif is added to can
+#    be set in the vm config.
+#
+# The default bridge is nbe-br.
+# The default interface is eth0.
+#
+#============================================================================
+
+import sys
+import types
+
+from xen.util import Brctl
+
+from xen.xend import XendRoot
+xroot = XendRoot.instance()
+
+class VifControl:
+
+    prefix = 'vifctl_'
+
+    DEFAULT_BRIDGE = 'nbe-br'
+    DEFAULT_INTERFACE = 'eth0'
+
+    def __init__(self):
+        self.name = 'vifctl'
+    
+    def main(self, args):
+        #print self.name, args
+        if len(args) < 2:
+            usage(args)
+        self.name = args[0]
+        cmd = self.prefix + args[1]
+        meth = getattr(self, cmd, self.unknown)
+        meth(args[1:])
+
+    def usage(self, args, out=sys.stderr):
+        print >>out, 'Missing command, try \n%s help' % self.name
+
+    def unknown(self, args, out=sys.stderr):
+        print >>out, 'Unknown command:', args[1]
+        self.help(out=out)
+        sys.exit(1)
+
+    def help(self, out=sys.stdout):
+        print >>out, 'Commands are:',
+        for x in vars(self):
+            if x.startswith(prefix):
+                cmd = x[len(prefix):]
+                print  >>out, cmd,
+        print >>out
+
+    def getparams(self, d, args, req=[]):
+        """Parse args of the form 'key=val'. Valid keys are the ones
+        in the dict 'd' passed in. If entries in 'd' have list values the
+        values of the keys are appended.
+
+        If 'req' is specified it is a list of required keys.
+        """
+        for x in args:
+            (k, v) = x.split('=')
+            k = k.strip()
+            v = v.strip()
+            if k not in d:
+                print >>sys.stderr, 'Invalid parameter: ', k
+                sys.exit(1)
+            vold = d[k]
+            if isinstance(vold , types.ListType):
+                d[k] = vold + v
+            else:
+                d[k] = v
+        for x in req:
+            if not d[x]:
+                print >>sys.stderr, 'Missing parameter:', x
+                sys.exit(1)
+        return d
+            
+    def vifctl_help(self, args):
+        self.help()
+
+    def default_bridge(self):
+        return xroot.get_config_value('bridge', self.DEFAULT_BRIDGE)
+
+    def default_interface(self):
+        return xroot.get_config_value('interface', self.DEFAULT_INTERFACE)
+    
+    def vifctl_init(self, args):
+        """Entry point for 'vifctl init'.
+        """
+        d = { 'bridge'   : self.default_bridge(),
+              'interface': self.default_interface() }
+        params = self.getparams(d, args[1:])
+        interface = params['interface']
+        bridge = params['bridge']
+        # Create bridge 'bridge'.
+        Brctl.bridge_create(bridge)
+        # Reconfigure so that 'interface' is added to 'bridge',
+        # and 'bridge' has the IP address from 'interface'.
+        Brctl.reconfigure(interface, bridge)
+        
+    def vifparams(self, args):
+        d = { 'vif'   : None,
+              'mac'   : None,
+              'bridge': self.default_bridge(),
+              'ipaddr': [] }
+        d = self.getparams(d, args, req=['vif', 'mac'])
+        return d
+
+    def vifctl_up(self, args):
+        """Entry point for 'vifctl up'.
+        """
+        params = self.vifparams(args[1:])
+        # Add the vif to its bridge.
+        Brctl.vif_bridge_add(params)
+        if params['ipaddr']:
+            # Add iptables rules for the ip addresses.
+            vif = params['vif']
+            for ipaddr in params['ipaddr']:
+               Brctl.vif_restrict_addr(vif, ipaddr)
+
+    def vifctl_down(self, args):
+        """Entry point for 'vifctl down'.
+        """
+        params = self.vifparams(args[1:])
+        # Remove the vif from its bridge.
+        Brctl.vif_bridge_rem(params)
+        if params['ip']:
+            # Remove iptables rules for the ip addresses.
+            vif = params['vif']
+            for ip in params['ip']:
+               Brctl.vif_restrict_addr(vif, ip, delete=1)
+
+
+if __name__ == "__main__":
+    VifControl().main(sys.argv)
diff --git a/tools/examples/xm_dom_create.py b/tools/examples/xm_dom_create.py
deleted file mode 100755 (executable)
index d84efb1..0000000
+++ /dev/null
@@ -1,406 +0,0 @@
-#!/usr/bin/env python
-
-import string
-import sys
-import os
-import os.path
-import time
-import socket
-import getopt
-import signal
-import syslog
-import xenctl.ip
-import xenctl.utils
-import xenctl.console_client
-
-from xenmgr import sxp
-from xenmgr import PrettyPrint
-from xenmgr.XendClient import server
-
-config_dir  = '/etc/xc/'
-config_file = xc_config_file = config_dir + 'defaults'
-
-def main_usage ():
-    print >>sys.stderr,"""
-Usage: %s <args>
-
-This tool is used to create and start new domains. It reads defaults
-from a file written in Python, having allowed variables to be set and
-passed into the file. Further command line arguments allow the
-defaults to be overridden. The defaults for each parameter are listed
-in [] brackets. Arguments are as follows:
-
-Arguments to control the parsing of the defaults file:
- -f config_file   -- Use the specified defaults script. 
-                     Default: ['%s']
- -L state_file    -- Load virtual machine memory state from state_file
- -D foo=bar       -- Set variable foo=bar before parsing config
-                     E.g. '-D vmid=3;ip=1.2.3.4'
- -h               -- Print extended help message, including all arguments
- -n               -- Dry run only, don't actually create domain
-                     Prints the config, suitable for -F.
- -q               -- Quiet - write output only to the system log
- -F domain_config -- Build domain using the config in the file.
-                     Suitable files can be made using '-n' to output a config.
-""" % (sys.argv[0], xc_config_file)
-
-def extra_usage ():
-    print >>sys.stderr,"""
-Arguments to override current config read from '%s':
- -c               -- Turn into console terminal after domain is created
- -k image         -- Path to kernel image ['%s']
- -r ramdisk       -- Path to ramdisk (or empty) ['%s']
- -b builder_fn    -- Function to use to build domain ['%s']
- -m mem_size      -- Initial memory allocation in MB [%dMB]
- -N domain_name   -- Set textual name of domain ['%s']
- -a auto_restart  -- Restart domain on exit, yes/no ['%d']
- -e vbd_expert    -- Safety catch to avoid some disk accidents ['%s'] 
- -d udisk,dev,rw  -- Add disk, partition, or virtual disk to domain. E.g. to 
-                     make partion sda4 available to the domain as hda1 with 
-                     read-write access: '-d phy:sda4,hda1,rw' To add 
-                     multiple disks use multiple -d flags or seperate with ';'
-                     Default: ['%s']
- -i vfr_ipaddr    -- Add IP address to the list which Xen will route to
-                     the domain. Use multiple times to add more IP addrs.
-                    Default: ['%s']
-
-Args to override the kernel command line, which is concatenated from these:
- -I cmdline_ip    -- Override 'ip=ipaddr:nfsserv:gateway:netmask::eth0:off'
-                     Default: ['%s']
- -R cmdline_root  -- Override root device parameters.
-                     Default: ['%s']
- -E cmdline_extra -- Override extra kernel args and rc script env vars.
-                     Default: ['%s']
-
-""" % (config_file,
-       image, ramdisk, builder_fn, mem_size, domain_name, auto_restart,
-       vbd_expert, 
-       printvbds( vbd_list ), 
-       reduce ( (lambda a,b: a+':'+b), vfr_ipaddr,'' )[1:],
-       cmdline_ip, cmdline_root, cmdline_extra)
-
-def config_usage (): pass
-
-def answer ( s ):
-    s = string.lower(s)
-    if s == 'yes' or s == 'true' or s == '1': return 1
-    return 0
-
-def printvbds ( v ):
-    s=''
-    for (a,b,c) in v:
-       s = s + '; %s,%s,%s' % (a,b,c)
-    return s[2:]
-
-def output(string):
-    global quiet
-    syslog.syslog(string)
-    if not quiet:
-        print string
-    return
-
-bail=False; dryrun=False; extrahelp=False; quiet = False
-image=''; ramdisk=''; builder_fn='linux'; restore=0; state_file=''
-mem_size=0; domain_name=''; vfr_ipaddr=[];
-vbd_expert='rr'; auto_restart=False;
-vbd_list = []; cmdline_ip = ''; cmdline_root=''; cmdline_extra=''
-pci_device_list = []; console_port = -1
-auto_console = False
-config_from_file = False
-
-##### Determine location of defaults file
-#####
-
-try:
-    opts, args = getopt.getopt(sys.argv[1:], "h?nqcf:F:D:k:r:b:m:N:a:e:d:i:I:R:E:L:" )
-
-    for opt in opts:
-       if opt[0] == '-f': config_file= opt[1]
-       if opt[0] == '-h' or opt[0] == '-?' : bail=True; extrahelp=True
-       if opt[0] == '-n': dryrun=True
-       if opt[0] == '-D': 
-           for o in string.split( opt[1], ';' ):
-               (l,r) = string.split( o, '=' )
-               exec "%s='%s'" % (l,r)
-        if opt[0] == '-q': quiet = True
-        if opt[0] == '-L': restore = True; state_file = opt[1]
-        if opt[0] == '-F': config_from_file = True; domain_config = opt[1]
-
-
-except getopt.GetoptError:
-    bail=True
-
-if not config_from_file:
-    try:
-        os.stat( config_file )
-    except:
-        try:
-            d = config_dir + config_file
-            os.stat( d )
-            config_file = d
-        except:
-            print >> sys.stderr, "Unable to open config file '%s'" % config_file
-            bail = True
-
-
-##### Parse the config file
-#####
-
-if not config_from_file:
-    if not quiet:
-        print "Parsing config file '%s'" % config_file
-
-    try:
-        execfile ( config_file )
-    except (AssertionError,IOError):
-        print >>sys.stderr,"Exiting %s" % sys.argv[0]
-        bail = True
-
-##### Print out config if necessary 
-##### 
-
-def bailout():
-    global extrahelp
-    main_usage()
-    config_usage()
-    if extrahelp: extra_usage()
-    sys.exit(1)
-
-if bail:
-    bailout()
-
-##### Parse any command line overrides 
-##### 
-
-x_vbd_list = []
-x_vfr_ipaddr  = []
-
-for opt in opts:
-    if opt[0] == '-k': image = opt[1]
-    if opt[0] == '-r': ramdisk = opt[1]
-    if opt[0] == '-b': builder_fn = opt[1]  
-    if opt[0] == '-m': mem_size = int(opt[1])
-    if opt[0] == '-C': cpu = int(opt[1])
-    if opt[0] == '-N': domain_name = opt[1]
-    if opt[0] == '-a': auto_restart = answer(opt[1])
-    if opt[0] == '-e': vbd_expert = opt[1]
-    if opt[0] == '-I': cmdline_ip = opt[1]
-    if opt[0] == '-R': cmdline_root = opt[1]
-    if opt[0] == '-E': cmdline_extra = opt[1]
-    if opt[0] == '-i': x_vfr_ipaddr.append(opt[1])
-    if opt[0] == '-c': auto_console = True
-    if opt[0] == '-d':
-       try:
-           vv = string.split(opt[1],';')           
-           for v in vv:
-               (udisk,dev,mode) = string.split(v,',')
-               x_vbd_list.append( (udisk,dev,mode) )
-       except:
-           print >>sys.stderr, "Invalid block device specification : %s" % opt[1]
-           sys.exit(1)
-
-if x_vbd_list: vbd_list = x_vbd_list
-if x_vfr_ipaddr: vfr_ipaddr = x_vfr_ipaddr
-
-syslog.openlog('xc_dom_create.py %s' % config_file, 0, syslog.LOG_DAEMON)
-
-def strip(pre, s):
-    if s.startswith(pre):
-        return s[len(pre):]
-    else:
-        return s
-
-def make_domain_config():
-    global builder_fn, image, ramdisk, mem_size, domain_name
-    global cpu
-    global cmdline, cmdline_ip, cmdline_root
-    global vfr_ipaddr, vbd_list, vbd_expert
-    
-    config = ['config',
-              ['name', domain_name ],
-              ['memory', mem_size ],
-              ]
-    if cpu:
-        config.append(['cpu', cpu])
-    
-    config_image = [ builder_fn ]
-    config_image.append([ 'kernel', os.path.abspath(image) ])
-    if ramdisk:
-        config_image.append([ 'ramdisk', os.path.abspath(ramdisk) ])
-    if cmdline_ip:
-        cmdline_ip = strip("ip=", cmdline_ip)
-        config_image.append(['ip', cmdline_ip])
-    if cmdline_root:
-        cmdline_root = strip("root=", cmdline_root)
-        config_image.append(['root', cmdline_root])
-    if cmdline_extra:
-        config_image.append(['args', cmdline_extra])
-    config.append(['image', config_image ])
-       
-    config_devs = []
-    for (uname, dev, mode) in vbd_list:
-        config_vbd = ['vbd',
-                      ['uname', uname],
-                      ['dev', dev ],
-                      ['mode', mode ] ]
-        if vbd_expert != 'rr':
-            config_vbd.append(['sharing', vbd_expert])
-        config_devs.append(['device', config_vbd])
-
-    for (bus, dev, func) in pci_device_list:
-        config_pci = ['pci',
-                      ['bus', bus ],
-                      ['dev', dev ],
-                      ['func', func] ]
-        config_devs.append(['device', config_pci])
-
-    # Add one vif with unspecified MAC.
-    config_devs.append(['device', ['vif']])
-
-    config += config_devs
-    
-    config_vfr = ['vfr']
-    idx = 0 # No way of saying which IP is for which vif?
-    for ip in vfr_ipaddr:
-        config_vfr.append(['vif', ['id', idx], ['ip', ip]])
-
-    config.append(config_vfr)
-    return config
-
-def parse_config_file(domain_file):
-    config = None
-    fin = None
-    try:
-        fin = file(domain_file, "rb")
-        config = sxp.parse(fin)
-        if len(config) >= 1:
-            config = config[0]
-        else:
-            raise StandardError("Invalid configuration")
-    except StandardError, ex:
-        print >> sys.stderr, "Error :", ex
-        sys.exit(1)
-    #finally:
-    if fin: fin.close()
-    return config
-
-# This function creates, builds and starts a domain, using the values
-# in the global variables, set above.  It is used in the subsequent
-# code for starting the new domain and rebooting it if appropriate.
-def make_domain(config):
-    """Create, build and start a domain.
-    Returns: [int] the ID of the new domain.
-    """
-    global restore
-
-    if restore:
-        dominfo = server.xend_domain_restore(state_file, config)
-    else:
-        dominfo = server.xend_domain_create(config)
-
-    dom = int(sxp.child_value(dominfo, 'id'))
-    console_info = sxp.child(dominfo, 'console')
-    if console_info:
-        console_port = int(sxp.child_value(console_info, 'port'))
-    else:
-        console_port = None
-    
-    if server.xend_domain_unpause(dom) < 0:
-        print "Error starting domain"
-        server.xend_domain_halt(dom)
-        sys.exit()
-
-    return (dom, console_port)
-
-PID_DIR = '/var/run/xendomains/'
-
-def pidfile(dom):
-    return PID_DIR + '%d.pid' % dom
-
-def mkpidfile():
-    global current_id
-    if not os.path.isdir(PID_DIR):
-        os.mkdir(PID_DIR)
-
-    fd = open(pidfile(current_id), 'w')
-    print >> fd, str(os.getpid())
-    fd.close()
-    return
-
-def rmpidfile():
-    global current_id
-    os.unlink(pidfile(current_id))
-
-def death_handler(dummy1,dummy2):
-    global current_id
-    os.unlink(pidfile(current_id))
-    output('Auto-restart daemon: daemon PID = %d for domain %d is now exiting'
-              % (os.getpid(), current_id))
-    sys.exit(0)
-    return
-
-#============================================================================
-# The starting / monitoring of the domain actually happens here...
-
-if config_from_file:
-    config = parse_config_file(domain_config)
-else:
-    config = make_domain_config()
-
-if dryrun:
-    print "# %s" % ' '.join(sys.argv)
-    PrettyPrint.prettyprint(config)
-    sys.exit(0)
-elif quiet:
-    pass
-else:
-    PrettyPrint.prettyprint(config)
-
-# start the domain and record its ID number
-(current_id, current_port) = make_domain(config)
-
-def start_msg(prefix, dom, port):
-    output(prefix + "VM started in domain %d" % dom)
-    if port:
-        output(prefix + "Console I/O available on TCP port %d." % port)
-
-start_msg('', current_id, current_port)
-
-if current_port and auto_console:
-    xenctl.console_client.connect('127.0.0.1', current_port)
-
-# if the auto_restart flag is set then keep polling to see if the domain is
-# alive - restart if it is not by calling make_domain() again (it's necessary
-# to update the id variable, since the new domain may have a new ID)
-
-#todo: Replace this - get xend to watch them.
-if auto_restart:
-    ARD = "Auto-restart daemon: "
-    # turn ourselves into a background daemon
-    try:
-       pid = os.fork()
-       if pid > 0:
-           sys.exit(0)
-       os.setsid()
-       pid = os.fork()
-       if pid > 0:
-            output(ARD + 'PID = %d' % pid)
-           sys.exit(0)
-        signal.signal(signal.SIGTERM,death_handler)
-    except OSError:
-       print >> sys.stderr, ARD+'Startup failed'
-       sys.exit(1)
-
-    mkpidfile()
-
-    while True:
-       time.sleep(1)
-        # todo: use new interface
-        info = xc.domain_getinfo(current_id, 1)
-       if info == [] or info[0]['dom'] != current_id:
-           output(ARD + "Domain %d terminated, restarting VM in new domain"
-                                     % current_id)
-            rmpidfile()
-           (current_id, current_port) = make_domain()
-            mkpidfile()
-            start_msg(ARD, current_id, current_port)
diff --git a/tools/lib/allocate.c b/tools/lib/allocate.c
deleted file mode 100644 (file)
index 600ebab..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "allocate.h"
-
-/** @file
- * Support for allocating memory.
- * Usable from user code or kernel code (with __KERNEL__ defined).
- * In user code will use GC if USE_GC is defined.
- */
-
-#ifdef __KERNEL__
-/*----------------------------------------------------------------------------*/
-#  include <linux/config.h>
-#  include <linux/slab.h>
-#  include <linux/string.h>
-#  include <linux/types.h>
-
-#  define DEFAULT_TYPE    0
-#  define MALLOC(n, type) kmalloc(n, type)
-#  define FREE(ptr)       kfree(ptr)
-
-/*----------------------------------------------------------------------------*/
-#else /* ! __KERNEL__ */
-
-#  include <stdlib.h>
-#  include <string.h>
-
-#  define DEFAULT_TYPE    0
-
-#ifdef USE_GC
-#  include "gc.h"
-#  define MALLOC(n, typ)  GC_malloc(n)
-#  define FREE(ptr)       (ptr=NULL)
-//typedef void *GC_PTR;
-//GC_PTR (*GC_oom_fn)(size_t n);
-#else
-#  define MALLOC(n, type) malloc(n)
-#  define FREE(ptr)       free(ptr)
-#endif
-
-/*----------------------------------------------------------------------------*/
-#endif
-
-/** Function to call when memory cannot be allocated. */
-AllocateFailedFn *allocate_failed_fn = NULL;
-
-/** Allocate memory and zero it.
- * The type is only relevant when calling from kernel code,
- * from user code it is ignored.
- * In kernel code the values accepted by kmalloc can be used:
- * GFP_USER, GFP_ATOMIC, GFP_KERNEL.
- *
- * @param size number of bytes to allocate
- * @param type memory type to allocate (kernel only)
- * @return pointer to the allocated memory or zero
- * if malloc failed
- */
-void *allocate_type(int size, int type){
-    void *p = MALLOC(size, type);
-    if(p){
-        memzero(p, size);
-    } else if(allocate_failed_fn){
-        allocate_failed_fn(size, type);
-    }
-    return p;
-}
-
-/** Allocate memory and zero it.
- *
- * @param size number of bytes to allocate
- * @return pointer to the allocated memory or zero
- * if malloc failed
- */
-void *allocate(int size){
-    return allocate_type(size, DEFAULT_TYPE);
-}
-
-/** Free memory allocated by allocate().
- * No-op if 'p' is null.
- *
- * @param p memory to free
- */
-void deallocate(void *p){
-    if(p){
-        FREE(p);
-    }
-}
-
-/** Set bytes to zero.
- * No-op if 'p' is null.
- *
- * @param p memory to zero
- * @param size number of bytes to zero
- */
-void memzero(void *p, int size){
-    if(p){
-        memset(p, 0, (size_t)size);
-    }
-}
-
diff --git a/tools/lib/allocate.h b/tools/lib/allocate.h
deleted file mode 100644 (file)
index 08bc67b..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _XEN_LIB_ALLOCATE_H_
-#define _XEN_LIB_ALLOCATE_H_
-
-/** Allocate memory for a given type, and cast. */
-#define ALLOCATE(ctype) (ctype *)allocate(sizeof(ctype))
-
-/** Allocate memory for a given type, and cast. */
-#define ALLOCATE_TYPE(ctype, type) (ctype *)allocate(sizeof(ctype))
-
-extern void *allocate_type(int size, int type);
-extern void *allocate(int size);
-extern void deallocate(void *);
-extern void memzero(void *p, int size);
-
-typedef void AllocateFailedFn(int size, int type);
-extern AllocateFailedFn *allocate_failed_fn;
-
-#endif /* _XEN_LIB_ALLOCATE_H_ */
-
-
-
-
-
-
-
-
-
diff --git a/tools/lib/debug.h b/tools/lib/debug.h
deleted file mode 100644 (file)
index 4f5228f..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _XEN_LIB_DEBUG_H_
-#define _XEN_LIB_DEBUG_H_
-
-#ifndef MODULE_NAME
-#define MODULE_NAME ""
-#endif
-
-#ifdef __KERNEL__
-#include <linux/config.h>
-#include <linux/kernel.h>
-
-#ifdef DEBUG
-
-#define dprintf(fmt, args...) printk(KERN_DEBUG   "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
-#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
-#define iprintf(fmt, args...) printk(KERN_INFO    "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
-#define eprintf(fmt, args...) printk(KERN_ERR     "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
-
-#else
-
-#define dprintf(fmt, args...) do {} while(0)
-#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME fmt, ##args)
-#define iprintf(fmt, args...) printk(KERN_INFO    "[INF] " MODULE_NAME fmt, ##args)
-#define eprintf(fmt, args...) printk(KERN_ERR     "[ERR] " MODULE_NAME fmt, ##args)
-
-#endif
-
-#else
-
-#include <stdio.h>
-
-#ifdef DEBUG
-
-#define dprintf(fmt, args...) fprintf(stdout, "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
-#define wprintf(fmt, args...) fprintf(stderr, "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
-#define iprintf(fmt, args...) fprintf(stderr, "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
-#define eprintf(fmt, args...) fprintf(stderr, "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
-
-#else
-
-#define dprintf(fmt, args...) do {} while(0)
-#define wprintf(fmt, args...) fprintf(stderr, "[WRN] " MODULE_NAME fmt, ##args)
-#define iprintf(fmt, args...) fprintf(stderr, "[INF] " MODULE_NAME fmt, ##args)
-#define eprintf(fmt, args...) fprintf(stderr, "[ERR] " MODULE_NAME fmt, ##args)
-
-#endif
-
-#endif
-
-/** Print format for an IP address.
- * See NIPQUAD(), HIPQUAD()
- */
-#define IPFMT "%u.%u.%u.%u"
-
-#endif /* ! _XEN_LIB_DEBUG_H_ */
diff --git a/tools/lib/enum.c b/tools/lib/enum.c
deleted file mode 100644 (file)
index 95f6e31..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or  (at your option) any later version. This library is 
- * distributed in the  hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#ifdef __KERNEL__
-#include <linux/errno.h>
-#else
-#include <errno.h>
-#endif
-
-#include "sys_string.h"
-#include "enum.h"
-
-/** Map an enum name to its value using a table.
- *
- * @param name enum name
- * @param defs enum definitions
- * @return enum value or -1 if not known
- */
-int enum_name_to_val(char *name, EnumDef *defs){
-    int val = -1;
-    for(; defs->name; defs++){
-       if(!strcmp(defs->name, name)){
-           val = defs->val;
-           break;
-       }
-    }
-    return val;
-}
-
-/** Map an enum value to its name using a table.
- *
- * @param val enum value
- * @param defs enum definitions
- * @param defs_n number of definitions
- * @return enum name or NULL if not known
- */
-char *enum_val_to_name(int val, EnumDef *defs){
-    char *name = NULL;
-    for(; defs->name; defs++){
-       if(val == defs->val){
-           name = defs->name;
-           break;
-       }
-    }
-    return name;
-}
-
diff --git a/tools/lib/enum.h b/tools/lib/enum.h
deleted file mode 100644 (file)
index db6e7b0..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or  (at your option) any later version. This library is 
- * distributed in the  hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#ifndef _XEN_LIB_ENUM_H_
-#define _XEN_LIB_ENUM_H_
-
-/** Mapping of an enum value to a name. */
-typedef struct EnumDef {
-    int val;
-    char *name;
-} EnumDef;
-
-extern int enum_name_to_val(char *name, EnumDef *defs);
-extern char *enum_val_to_name(int val, EnumDef *defs);
-
-#endif /* _XEN_LIB_ENUM_H_ */
diff --git a/tools/lib/file_stream.c b/tools/lib/file_stream.c
deleted file mode 100644 (file)
index 40391f7..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/** @file
- * An IOStream implementation using FILE*.
- */
-#ifndef __KERNEL__
-#include <stdio.h>
-#include <stdlib.h>
-#include "allocate.h"
-#include "file_stream.h"
-
-static int file_read(IOStream *s, void *buf, size_t n);
-static int file_write(IOStream *s, const void *buf, size_t n);
-static int file_error(IOStream *s);
-static int file_close(IOStream *s);
-static void file_free(IOStream *s);
-static int file_flush(IOStream *s);
-
-/** Methods used by a FILE* IOStream. */
-static const IOMethods file_methods = {
-    read:  file_read,
-    write: file_write,
-    error: file_error,
-    close: file_close,
-    free:  file_free,
-    flush: file_flush,
-};
-
-/** IOStream for stdin. */
-static IOStream _iostdin = {
-    methods: &file_methods,
-    data: (void*)1,
-};
-
-/** IOStream for stdout. */
-static IOStream _iostdout = {
-    methods: &file_methods,
-    data: (void*)2,
-};
-
-/** IOStream for stderr. */
-static IOStream _iostderr = {
-    methods: &file_methods,
-    data: (void*)3,
-};
-
-/** IOStream for stdin. */
-IOStream *iostdin = &_iostdin;
-
-/** IOStream for stdout. */
-IOStream *iostdout = &_iostdout;
-
-/** IOStream for stderr. */
-IOStream *iostderr = &_iostderr;
-
-/** Get the underlying FILE*.
- * 
- * @param s file stream
- * @return the stream s wraps
- */
-static inline FILE *get_file(IOStream *s){
-    switch((long)s->data){
-    case 1: s->data = stdin; break;
-    case 2: s->data = stdout; break;
-    case 3: s->data = stderr; break;
-    }
-    return (FILE*)s->data;
-}
-
-/** Control buffering on the underlying stream, like setvbuf().
- *
- * @param io file stream
- * @param buf buffer
- * @param mode buffering mode (see man setvbuf())
- * @param size buffer size
- * @return 0 on success, non-zero otherwise
- */
-int file_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size){
-    return setvbuf(get_file(io), buf, mode, size);
-}
-
-/** Write to the underlying stream using fwrite();
- *
- * @param stream input
- * @param buf where to put input
- * @param n number of bytes to write
- * @return number of bytes written
- */
-static int file_write(IOStream *s, const void *buf, size_t n){
-    return fwrite(buf, 1, n, get_file(s));
-}
-
-/** Read from the underlying stream using fread();
- *
- * @param stream input
- * @param buf where to put input
- * @param n number of bytes to read
- * @return number of bytes read
- */
-static int file_read(IOStream *s, void *buf, size_t n){
-    return fread(buf, 1, n, get_file(s));
-}
-
-/** Fush the underlying stream using fflush().
- *
- * @param s file stream
- * @return 0 on success, error code otherwise
- */
-static int file_flush(IOStream *s){
-    return fflush(get_file(s));
-}
-
-/** Check if a stream has an error.
- *
- * @param s file stream
- * @return 1 if has an error, 0 otherwise
- */
-static int file_error(IOStream *s){
-    return ferror(get_file(s));
-}
-
-/** Close a file stream.
- *
- * @param s file stream to close
- * @return result of the close
- */
-static int file_close(IOStream *s){
-    return fclose(get_file(s));
-}
-
-/** Free a file stream.
- *
- * @param s file stream
- */
-static void file_free(IOStream *s){
-    // Do nothing - fclose does it all?
-}
-
-/** Create an IOStream for a stream.
- *
- * @param f stream to wrap
- * @return new IOStream using f for i/o
- */
-IOStream *file_stream_new(FILE *f){
-    IOStream *io = ALLOCATE(IOStream);
-    if(io){
-       io->methods = &file_methods;
-       io->data = (void*)f;
-    }
-    return io;
-}
-
-/** IOStream version of fopen().
- *
- * @param file name of the file to open
- * @param flags giving the mode to open in (as for fopen())
- * @return new stream for the open file, or 0 if failed
- */
-IOStream *file_stream_fopen(const char *file, const char *flags){
-    IOStream *io = 0;
-    FILE *fin = fopen(file, flags);
-    if(fin){
-       io = file_stream_new(fin);
-       if(!io){
-           fclose(fin);
-           //free(fin); // fclose frees ?
-       }
-    }
-    return io;
-}
-
-/** IOStream version of fdopen().
- *
- * @param fd file descriptor
- * @param flags giving the mode to open in (as for fdopen())
- * @return new stream for the open file, or 0 if failed
- */
-IOStream *file_stream_fdopen(int fd, const char *flags){
-    IOStream *io = 0;
-    FILE *fin = fdopen(fd, flags);
-    if(fin){
-       io = file_stream_new(fin);
-    }
-    return io;
-}
-#endif
diff --git a/tools/lib/file_stream.h b/tools/lib/file_stream.h
deleted file mode 100644 (file)
index 36a0f92..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _XEN_LIB_FILE_STREAM_H_
-#define _XEN_LIB_FILE_STREAM_H_
-
-#ifndef __KERNEL__
-#include "iostream.h"
-#include <stdio.h>
-
-extern IOStream *file_stream_new(FILE *f);
-extern IOStream *file_stream_fopen(const char *file, const char *flags);
-extern IOStream *file_stream_fdopen(int fd, const char *flags);
-extern IOStream get_stream_stdout(void);
-extern IOStream get_stream_stderr(void);
-extern IOStream get_stream_stdin(void);
-
-extern int file_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size);
-#endif
-#endif /* !_XEN_LIB_FILE_STREAM_H_ */
diff --git a/tools/lib/gzip_stream.c b/tools/lib/gzip_stream.c
deleted file mode 100644 (file)
index af46023..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/* $Id: gzip_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */
-/*
- * Copyright (C) 2003 Hewlett-Packard Company.
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/** @file
- * An IOStream implementation using zlib gzFile to provide
- * compression and decompression.
- */
-#ifndef __KERNEL__
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "zlib.h"
-
-#include "allocate.h"
-#include "gzip_stream.h"
-
-static int gzip_read(IOStream *s, void *buf, size_t n);
-static int gzip_write(IOStream *s, const void *buf, size_t n);
-static int gzip_error(IOStream *s);
-static int gzip_close(IOStream *s);
-static void gzip_free(IOStream *s);
-static int gzip_flush(IOStream *s);
-
-/** Methods used by a gzFile* IOStream. */
-static const IOMethods gzip_methods = {
-    read: gzip_read,
-    write: gzip_write,
-    error: gzip_error,
-    close: gzip_close,
-    free:  gzip_free,
-    flush: gzip_flush,
-};
-
-/** Get the underlying gzFile*.
- * 
- * @param s gzip stream
- * @return the stream s wraps
- */
-static inline gzFile get_gzfile(IOStream *s){
-    return (gzFile)s->data;
-}
-
-/** Write to the underlying stream.
- *
- * @param stream destination
- * @param buf data
- * @param n number of bytes to write
- * @return number of bytes written
- */
-static int gzip_write(IOStream *s, const void *buf, size_t n){
-    return gzwrite(get_gzfile(s), (void*)buf, n);
-}
-
-/** Read from the underlying stream.
- *
- * @param stream input
- * @param buf where to put input
- * @param n number of bytes to read
- * @return number of bytes read
- */
-static int gzip_read(IOStream *s, void *buf, size_t n){
-    return gzread(get_gzfile(s), buf, n);
-}
-
-/** Flush the underlying stream.
- *
- * @param s gzip stream
- * @return 0 on success, error code otherwise
- */
-static int gzip_flush(IOStream *s){
-    //return gzflush(get_gzfile(s), Z_NO_FLUSH);
-    return gzflush(get_gzfile(s), Z_SYNC_FLUSH);
-    //return gzflush(get_gzfile(s), Z_FULL_FLUSH);
-}
-
-/** Check if a stream has an error.
- *
- * @param s gzip stream
- * @return 1 if has an error, 0 otherwise
- */
-static int gzip_error(IOStream *s){
-    int err;
-    gzFile *gz = get_gzfile(s);
-    gzerror(gz, &err);
-    return (err == Z_ERRNO ? 1 /* ferror(gzfile(gz)) */ : err);
-}
-
-/** Close a gzip stream.
- *
- * @param s gzip stream to close
- * @return result of the close
- */
-static int gzip_close(IOStream *s){
-    return gzclose(get_gzfile(s));
-}
-
-/** Free a gzip stream.
- *
- * @param s gzip stream
- */
-static void gzip_free(IOStream *s){
-    // Do nothing - fclose does it all?
-}
-
-/** Create an IOStream for a gzip stream.
- *
- * @param f stream to wrap
- * @return new IOStream using f for i/o
- */
-IOStream *gzip_stream_new(gzFile *f){
-    IOStream *io = ALLOCATE(IOStream);
-    if(io){
-       io->methods = &gzip_methods;
-       io->data = (void*)f;
-    }
-    return io;
-}
-
-/** IOStream version of fopen().
- *
- * @param file name of the file to open
- * @param flags giving the mode to open in (as for fopen())
- * @return new stream for the open file, or NULL if failed
- */
-IOStream *gzip_stream_fopen(const char *file, const char *flags){
-    IOStream *io = NULL;
-    gzFile *fgz;
-    fgz = gzopen(file, flags);
-    if(fgz){
-       io = gzip_stream_new(fgz);
-       if(!io){
-           gzclose(fgz);
-           //free(fgz); // gzclose frees ?
-       }
-    }
-    return io;
-}
-
-/** IOStream version of fdopen().
- *
- * @param fd file descriptor
- * @param flags giving the mode to open in (as for fdopen())
- * @return new stream for the open file, or NULL if failed
- */
-IOStream *gzip_stream_fdopen(int fd, const char *flags){
-    IOStream *io = NULL;
-    gzFile *fgz;
-    fgz = gzdopen(fd, flags);
-    if(fgz){
-       io = gzip_stream_new(fgz);
-    }
-    return io;
-}
-#endif
diff --git a/tools/lib/gzip_stream.h b/tools/lib/gzip_stream.h
deleted file mode 100644 (file)
index cf76d25..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#/* $Id: gzip_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */
-/*
- * Copyright (C) 2003 Hewlett-Packard Company.
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _SP_GZIP_STREAM_H_
-#define _SP_GZIP_STREAM_H_
-
-#ifndef __KERNEL__
-#include "iostream.h"
-#include "zlib.h"
-
-extern IOStream *gzip_stream_new(gzFile *f);
-extern IOStream *gzip_stream_fopen(const char *file, const char *flags);
-extern IOStream *gzip_stream_fdopen(int fd, const char *flags);
-#endif
-#endif /* !_SP_FILE_STREAM_H_ */
diff --git a/tools/lib/hash_table.c b/tools/lib/hash_table.c
deleted file mode 100644 (file)
index 13da946..0000000
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifdef __KERNEL__
-#  include <linux/config.h>
-#  include <linux/module.h>
-#  include <linux/kernel.h>
-#  include <linux/errno.h>
-#else
-#  include <errno.h>
-#  include <stddef.h>
-#endif
-
-//#include <limits.h>
-
-#include "allocate.h"
-#include "hash_table.h"
-
-/** @file
- * Base support for hashtables.
- *
- * Hash codes are reduced modulo the number of buckets to index tables,
- * so there is no need for hash functions to limit the range of hashcodes.
- * In fact it is assumed that hashcodes do not change when the number of
- * buckets in the table changes.
- */
-
-/*==========================================================================*/
-/** Number of bits in half a word. */
-//#if __WORDSIZE == 64
-//#define HALF_WORD_BITS 32
-//#else
-#define HALF_WORD_BITS 16
-//#endif
-
-/** Mask for lo half of a word. On 32-bit this is 
- * (1<<16) - 1 = 65535 = 0xffff
- * It's 4294967295 = 0xffffffff on 64-bit.
- */
-#define LO_HALF_MASK ((1 << HALF_WORD_BITS) - 1)
-
-/** Get the lo half of a word. */
-#define LO_HALF(x) ((x) & LO_HALF_MASK)
-
-/** Get the hi half of a word. */
-#define HI_HALF(x) ((x) >> HALF_WORD_BITS)
-
-/** Do a full hash on both inputs, using DES-style non-linear scrambling.
- * Both inputs are replaced with the results of the hash.
- *
- * @param pleft input/output word
- * @param pright input/output word
- */
-void pseudo_des(unsigned long *pleft, unsigned long *pright){
-    // Bit-rich mixing constant.
-    static const unsigned long a_mixer[] = {
-        0xbaa96887L, 0x1e17d32cL, 0x03bcdc3cL, 0x0f33d1b2L, };
-
-    // Bit-rich mixing constant.
-    static const unsigned long b_mixer[] = {
-        0x4b0f3b58L, 0xe874f0c3L, 0x6955c5a6L, 0x55a7ca46L, };
-
-    // Number of iterations - must be 2 or 4.
-    static const int ncycle = 4;
-    //static const int ncycle = 2;
-
-    unsigned long left = *pleft, right = *pright;
-    unsigned long v, v_hi, v_lo;
-    int i;
-
-    for(i=0; i<ncycle; i++){
-        // Flip some bits in right to get v.
-        v = right;
-        v ^= a_mixer[i];
-        // Get lo and hi halves of v.
-        v_lo = LO_HALF(v);
-        v_hi = HI_HALF(v);
-        // Non-linear mix of the halves of v.
-        v = ((v_lo * v_lo) + ~(v_hi * v_hi));
-        // Swap the halves of v.
-        v = (HI_HALF(v) | (LO_HALF(v) << HALF_WORD_BITS));
-        // Flip some bits.
-        v ^= b_mixer[i];
-        // More non-linear mixing.
-        v += (v_lo * v_hi);
-        v ^= left;
-        left = right;
-        right = v;
-    }
-    *pleft = left;
-    *pright = right;
-}
-
-/** Hash a string.
- *
- * @param s input to hash
- * @return hashcode
- */
-Hashcode hash_string(char *s){
-    Hashcode h = 0;
-    if(s){
-        for( ; *s; s++){
-            h = hash_2ul(h, *s);
-        }
-    }
-    return h;
-}
-
-/** Get the bucket for a hashcode in a hash table.
- *
- * @param table to get bucket from
- * @param hashcode to get bucket for
- * @return bucket
- */
-inline HTBucket * get_bucket(HashTable *table, Hashcode hashcode){
-    return table->buckets + (hashcode % table->buckets_n);
-}
-
-/** Initialize a hash table.
- * Can be safely called more than once.
- *
- * @param table to initialize
- */
-void HashTable_init(HashTable *table){
-    int i;
-
-    if(!table->init_done){
-        table->init_done = 1;
-        table->next_id = 0;
-        for(i=0; i<table->buckets_n; i++){
-            HTBucket *bucket = get_bucket(table, i);
-            bucket->head = 0;
-            bucket->count = 0;
-        }
-        table->entry_count = 0;
-    }
-}
-
-/** Allocate a new hashtable.
- * If the number of buckets is not positive the default is used.
- * The number of buckets should usually be prime.
- *
- * @param buckets_n number of buckets
- * @return new hashtable or null
- */
-HashTable *HashTable_new(int buckets_n){
-    HashTable *z = ALLOCATE(HashTable);
-    if(!z) goto exit;
-    if(buckets_n <= 0){
-        buckets_n = HT_BUCKETS_N;
-    }
-    z->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
-    if(!z->buckets){
-        deallocate(z);
-        z = 0;
-        goto exit;
-    }
-    z->buckets_n = buckets_n;
-    HashTable_init(z);
-  exit:
-    return z;
-}
-
-/** Free a hashtable.
- * Any entries are removed and freed.
- *
- * @param h hashtable (ignored if null)
- */
-void HashTable_free(HashTable *h){
-    if(h){
-        HashTable_clear(h);
-        deallocate(h->buckets);
-        deallocate(h);
-    }
-}
-
-/** Push an entry on the list in the bucket for a given hashcode.
- *
- * @param table to add entry to
- * @param hashcode for the entry
- * @param entry to add
- */
-static inline void push_on_bucket(HashTable *table, Hashcode hashcode,
-                                 HTEntry *entry){
-    HTBucket *bucket;
-    HTEntry *old_head;
-
-    bucket = get_bucket(table, hashcode);
-    old_head = bucket->head;
-    bucket->count++;
-    bucket->head = entry;
-    entry->next = old_head;
-}
-
-/** Change the number of buckets in a hashtable.
- * No-op if the number of buckets is not positive.
- * Existing entries are reallocated to buckets based on their hashcodes.
- * The table is unmodified if the number of buckets cannot be changed.
- *
- * @param table hashtable
- * @param buckets_n new number of buckets
- * @return 0 on success, error code otherwise
- */
-int HashTable_set_buckets_n(HashTable *table, int buckets_n){
-    int err = 0;
-    HTBucket *old_buckets = table->buckets;
-    int old_buckets_n = table->buckets_n;
-    int i;
-
-    if(buckets_n <= 0){
-        err = -EINVAL;
-        goto exit;
-    }
-    table->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
-    if(!table->buckets){
-        err = -ENOMEM;
-        table->buckets = old_buckets;
-        goto exit;
-    }
-    table->buckets_n = buckets_n;
-    for(i=0; i<old_buckets_n; i++){
-        HTBucket *bucket = old_buckets + i;
-        HTEntry *entry, *next;
-        for(entry = bucket->head; entry; entry = next){
-            next = entry->next;
-            push_on_bucket(table, entry->hashcode, entry);
-        }
-    }
-    deallocate(old_buckets);
-  exit:
-    return err;
-}
-
-/** Adjust the number of buckets so the table is neither too full nor too empty.
- * The table is unmodified if adjusting fails.
- *
- * @param table hash table
- * @param buckets_min minimum number of buckets (use default if 0 or negative)
- * @return 0 on success, error code otherwise
- */
-int HashTable_adjust(HashTable *table, int buckets_min){
-    int buckets_n = 0;
-    int err = 0;
-    if(buckets_min <= 0) buckets_min = HT_BUCKETS_N;
-    if(table->entry_count >= table->buckets_n){
-        // The table is dense - expand it.
-        buckets_n = 2 * table->buckets_n;
-    } else if((table->buckets_n > buckets_min) &&
-              (4 * table->entry_count < table->buckets_n)){
-        // The table is more than minimum size and sparse - shrink it.
-        buckets_n = 2 * table->entry_count;
-        if(buckets_n < buckets_min) buckets_n = buckets_min;
-    }
-    if(buckets_n){
-        err = HashTable_set_buckets_n(table, buckets_n);
-    }
-    return err;
-}
-
-/** Allocate a new entry for a given value.
- *
- * @param value to put in the entry
- * @return entry, or 0 on failure
- */
-HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value){
-    HTEntry *z = ALLOCATE(HTEntry);
-    if(z){
-        z->hashcode = hashcode;
-        z->key = key;
-        z->value = value;
-    }
-    return z;
-}
-
-/** Free an entry.
- *
- * @param z entry to free
- */
-inline void HTEntry_free(HTEntry *z){
-    if(z){
-        deallocate(z);
-    }
-}
-
-/** Free an entry in a hashtable.
- * The table's entry_free_fn is used is defined, otherwise 
- * the HTEntry itself is freed.
- *
- * @param table hashtable
- * @param entry to free
- */
-inline void HashTable_free_entry(HashTable *table, HTEntry *entry){
-    if(!entry)return;
-    if(table && table->entry_free_fn){
-        table->entry_free_fn(table, entry);
-    } else {
-        HTEntry_free(entry);
-    }
-}
-
-/** Get the first entry satisfying a test from the bucket for the
- * given hashcode.
- *
- * @param table to look in
- * @param hashcode indicates the bucket
- * @param test_fn test to apply to elements
- * @param arg first argument to calls to test_fn
- * @return entry found, or 0
- */
-inline HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
-                                     TableTestFn *test_fn, TableArg arg){
-    HTBucket *bucket;
-    HTEntry *entry = 0;
-    HTEntry *next;
-
-    bucket = get_bucket(table, hashcode);
-    for(entry = bucket->head; entry; entry = next){
-        next = entry->next;
-        if(test_fn(arg, table, entry)){
-            break;
-        }
-    }
-    return entry;
-}
-
-/** Test hashtable keys for equality.
- * Uses the table's key_equal_fn if defined, otherwise pointer equality.
- *
- * @param key1 key to compare
- * @param key2 key to compare
- * @return 1 if equal, 0 otherwise
- */
-inline int HashTable_key_equal(HashTable *table, void *key1, void *key2){
-    return (table->key_equal_fn ? table->key_equal_fn(key1, key2) : key1==key2);
-}
-
-/** Compute the hashcode of a hashtable key.
- * The table's key_hash_fn is used if defined, otherwise the address of
- * the key is hashed.
- *
- * @param table hashtable
- * @param key to hash
- * @return hashcode
- */
-inline Hashcode HashTable_key_hash(HashTable *table, void *key){
-    return (table->key_hash_fn ? table->key_hash_fn(key) : hash_ul((unsigned long)key));
-}
-
-/** Test if an entry has a given key.
- *
- * @param arg containing key to test for
- * @param table the entry is in
- * @param entry to test
- * @return 1 if the entry has the key, 0 otherwise
- */
-static inline int has_key(TableArg arg, HashTable *table, HTEntry *entry){
-    return HashTable_key_equal(table, arg.ptr, entry->key);
-}
-
-/** Get an entry with a given key.
- *
- * @param table to search
- * @param key to look for
- * @return entry if found, null otherwise
- */
-#if 0
-inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
-    TableArg arg = { ptr: key };
-    return HashTable_find_entry(table, HashTable_key_hash(table, key), has_key, arg);
-}
-#else
-inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
-    Hashcode hashcode;
-    HTBucket *bucket;
-    HTEntry *entry = 0;
-    HTEntry *next;
-
-    hashcode = HashTable_key_hash(table, key);
-    bucket = get_bucket(table, hashcode);
-    for(entry = bucket->head; entry; entry = next){
-        next = entry->next;
-        if(HashTable_key_equal(table, key, entry->key)){
-            break;
-        }
-    }
-    return entry;
-}
-#endif
-
-/** Get the value of an entry with a given key.
- *
- * @param table to search
- * @param key to look for
- * @return value if an entry was found, null otherwise
- */
-inline void * HashTable_get(HashTable *table, void *key){
-    HTEntry *entry = HashTable_get_entry(table, key);
-    return (entry ? entry->value : 0);
-}
-
-/** Print the buckets in a table.
- *
- * @param table to print
- */
-void show_buckets(HashTable *table, IOStream *io){
-    int i,j ;
-    IOStream_print(io, "entry_count=%d buckets_n=%d\n", table->entry_count, table->buckets_n);
-    for(i=0; i<table->buckets_n; i++){
-        if(0 || table->buckets[i].count>0){
-            IOStream_print(io, "bucket %3d %3d %10p ", i,
-                        table->buckets[i].count,
-                        table->buckets[i].head);
-            for(j = table->buckets[i].count; j>0; j--){
-                IOStream_print(io, "+");
-            }
-            IOStream_print(io, "\n");
-        }
-    }
-    HashTable_print(table, io); 
-}
-    
-/** Print an entry in a table.
- *
- * @param entry to print
- * @param arg a pointer to an IOStream to print to
- * @return 0
- */
-static int print_entry(TableArg arg, HashTable *table, HTEntry *entry){
-    IOStream *io = (IOStream*)arg.ptr;
-    IOStream_print(io, " b=%4lx h=%08lx i=%08lx |-> e=%8p k=%8p v=%8p\n",
-                entry->hashcode % table->buckets_n,
-                entry->hashcode,
-                entry->index,
-                entry, entry->key, entry->value);
-    return 0;
-}
-
-/** Print a hash table.
- *
- * @param table to print
- */
-void HashTable_print(HashTable *table, IOStream *io){
-    IOStream_print(io, "{\n");
-    HashTable_map(table, print_entry, (TableArg){ ptr: io });
-    IOStream_print(io, "}\n");
-}
-/*==========================================================================*/
-
-/** Get the next entry id to use for a table.
- *
- * @param table hash table
- * @return non-zero entry id
- */
-static inline unsigned long get_next_id(HashTable *table){
-    unsigned long id;
-
-    if(table->next_id == 0){
-        table->next_id = 1;
-    }
-    id = table->next_id++;
-    return id;
-}
-
-/** Add an entry to the bucket for the
- * given hashcode.
- *
- * @param table to insert in
- * @param hashcode indicates the bucket
- * @param key to add an entry for
- * @param value to add an entry for
- * @return entry on success, 0 on failure
- */
-inline HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value){
-    HTEntry *entry = HTEntry_new(hashcode, key, value);
-    if(entry){
-        entry->index = get_next_id(table);
-        push_on_bucket(table, hashcode, entry);
-        table->entry_count++;
-    }
-    return entry;
-}
-
-/** Move the front entry for a bucket to the correct point in the bucket order as
- * defined by the order function. If this is called every time a new entry is added
- * the bucket will be maintained in sorted order.
- *
- * @param table to modify
- * @param hashcode indicates the bucket
- * @param order entry comparison function
- * @return 0 if an entry was moved, 1 if not
- */
-int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order){
-    HTEntry *new_entry = NULL, *prev = NULL, *entry = NULL;
-    HTBucket *bucket;
-    int err = 1;
-
-    bucket = get_bucket(table, hashcode);
-    new_entry = bucket->head;
-    if(!new_entry || !new_entry->next) goto exit;
-    for(entry = new_entry->next; entry; prev = entry, entry = entry->next){
-        if(order(new_entry, entry) <= 0) break;
-    }
-    if(prev){
-        err = 0;
-        bucket->head = new_entry->next; 
-        new_entry->next = entry;
-        prev->next = new_entry;
-    }
-  exit:
-    return err;
-}
-
-/** Add an entry to a hashtable.
- * The entry is added to the bucket for its key's hashcode.
- *
- * @param table to insert in
- * @param key to add an entry for
- * @param value to add an entry for
- * @return entry on success, 0 on failure
- */
-inline HTEntry * HashTable_add(HashTable *table, void *key, void *value){
-    return HashTable_add_entry(table, HashTable_key_hash(table, key), key, value);
-}
-
-
-/** Remove entries satisfying a test from the bucket for the
- * given hashcode. 
- *
- * @param table to remove from
- * @param hashcode indicates the bucket
- * @param test_fn test to apply to elements
- * @param arg first argument to calls to test_fn
- * @return number of entries removed
- */
-inline int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
-                                 TableTestFn *test_fn, TableArg arg){
-    HTBucket *bucket;
-    HTEntry *entry, *prev = 0, *next;
-    int removed_count = 0;
-
-    bucket = get_bucket(table, hashcode);
-    for(entry = bucket->head; entry; entry = next){
-        next = entry->next;
-        if(test_fn(arg, table, entry)){
-            if(prev){
-                prev->next = next;
-            } else {
-                bucket->head = next;
-            }
-            bucket->count--;
-            table->entry_count--;
-            removed_count++;
-            HashTable_free_entry(table, entry);
-            entry = 0;
-        }
-        prev = entry;
-    }
-    return removed_count;
-}
-
-/** Remove entries with a given key. 
- *
- * @param table to remove from
- * @param key of entries to remove
- * @return number of entries removed
- */
-inline int HashTable_remove(HashTable *table, void *key){
-#if 1
-    Hashcode hashcode;
-    HTBucket *bucket;
-    HTEntry *entry, *prev = 0, *next;
-    int removed_count = 0;
-
-    hashcode = HashTable_key_hash(table, key);
-    bucket = get_bucket(table, hashcode);
-    for(entry = bucket->head; entry; entry = next){
-        next = entry->next;
-        if(HashTable_key_equal(table, key, entry->key)){
-            if(prev){
-                prev->next = next;
-            } else {
-                bucket->head = next;
-            }
-            bucket->count--;
-            table->entry_count--;
-            removed_count++;
-            HashTable_free_entry(table, entry);
-            entry = 0;
-        }
-        prev = entry;
-    }
-    return removed_count;
-#else
-    return HashTable_remove_entry(table, HashTable_key_hash(table, key),
-                                 has_key, (TableArg){ ptr: key});
-#endif
-}
-
-/** Remove (and free) all the entries in a bucket.
- *
- * @param bucket to clear
- */
-static inline void bucket_clear(HashTable *table, HTBucket *bucket){
-    HTEntry *entry, *next;
-
-    for(entry = bucket->head; entry; entry = next){
-        next = entry->next;
-        HashTable_free_entry(table, entry);
-    }
-    bucket->head = 0;
-    table->entry_count -= bucket->count;
-    bucket->count = 0;
-}
-
-/** Remove (and free) all the entries in a table.
- *
- * @param table to clear
- */
-void HashTable_clear(HashTable *table){
-    int i, n = table->buckets_n;
-
-    for(i=0; i<n; i++){
-        bucket_clear(table, table->buckets + i);
-    }
-}
diff --git a/tools/lib/hash_table.h b/tools/lib/hash_table.h
deleted file mode 100644 (file)
index 6d7e76f..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/* $Id: hash_table.h,v 1.1 2004/03/30 16:21:26 mjw Exp $ */
-/*
- * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _XEN_LIB_HASH_TABLE_H_
-#define _XEN_LIB_HASH_TABLE_H_
-
-#include "iostream.h"
-
-typedef unsigned long Hashcode;
-
-/** Type used to pass parameters to table functions. */
-typedef union TableArg {
-    unsigned long ul;
-    void *ptr;
-} TableArg;
-
-/** An entry in a bucket list. */
-typedef struct HTEntry {
-    /** Hashcode of the entry's key. */
-    Hashcode hashcode;
-    /** Identifier for this entry in the table. */
-    int index;
-    /** The key for this entry. */
-    void *key;
-    /** The value in this entry. */
-    void *value;
-    /** The next entry in the list. */
-    struct HTEntry *next;
-} HTEntry;
-
-/** A bucket in a rule table. */
-typedef struct HTBucket {
-    /** Number of entries in the bucket. */
-    int count;
-    /** First entry in the bucket (may be null). */
-    HTEntry *head;
-} HTBucket;
-
-/** Default number of buckets in a hash table.
- * You want enough buckets so the lists in the buckets will typically be short.
- * It's a good idea if this is prime, since that will help to spread hashcodes
- * around the table.
- */
-//#define HT_BUCKETS_N 1
-//#define HT_BUCKETS_N 3
-//#define HT_BUCKETS_N 7
-//#define HT_BUCKETS_N 17
-//#define HT_BUCKETS_N 97
-//#define HT_BUCKETS_N 211
-//#define HT_BUCKETS_N 401
-#define HT_BUCKETS_N 1021
-
-typedef struct HashTable HashTable;
-
-/** Type for a function used to select table entries. */
-typedef int TableTestFn(TableArg arg, HashTable *table, HTEntry *entry);
-
-/** Type for a function to map over table entries. */
-typedef int TableMapFn(TableArg arg, HashTable *table, HTEntry *entry);
-
-/** Type for a function to free table entries. */
-typedef void TableFreeFn(HashTable *table, HTEntry *entry);
-
-/** Type for a function to hash table keys. */
-typedef Hashcode TableHashFn(void *key);
-
-/** Type for a function to test table keys for equality. */
-typedef int TableEqualFn(void *key1, void *key2);
-
-/** Type for a function to order table entries. */
-typedef int TableOrderFn(HTEntry *e1, HTEntry *e2);
-
-/** General hash table.
- * A hash table with a list in each bucket.
- * Functions can be supplied for freeing entries, hashing keys, and comparing keys.
- * These all default to 0, when default behaviour treating keys as integers is used.
- */
-struct HashTable {
-    /** Flag indicating whether the table has been initialised. */
-    int init_done;
-    /** Next value for the id field in inserted rules. */
-    unsigned long next_id;
-    /** Number of buckets in the bucket array. */
-    int buckets_n;
-    /** Array of buckets, each with its own list. */
-    HTBucket *buckets;
-    /** Number of entries in the table. */
-    int entry_count;
-    /** Function to free keys and values in entries. */
-    TableFreeFn *entry_free_fn;
-    /** Function to hash keys. */
-    TableHashFn *key_hash_fn;
-    /** Function to compare keys for equality. */
-    TableEqualFn *key_equal_fn;
-    /** Place for the user of the table to hang extra data. */
-    void *user_data;
-};
-
-extern HashTable *HashTable_new(int bucket_n);
-extern void HashTable_free(HashTable *table);
-extern HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value);
-extern void HTEntry_free(HTEntry *entry);
-extern int HashTable_set_bucket_n(HashTable *table, int bucket_n);
-extern void HashTable_clear(HashTable *table);
-extern HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value);
-extern HTEntry * HashTable_get_entry(HashTable *table, void *key);
-extern HTEntry * HashTable_add(HashTable *table, void *key, void *value);
-extern void * HashTable_get(HashTable *table, void *key);
-extern int HashTable_remove(HashTable *table, void *key);
-extern HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
-                                      TableTestFn *test_fn, TableArg arg);
-extern int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
-                                   TableTestFn *test_fn, TableArg arg);
-//extern int HashTable_map(HashTable *table, TableMapFn *map_fn, TableArg arg);
-extern void HashTable_print(HashTable *table, IOStream *out);
-extern int HashTable_set_buckets_n(HashTable *table, int buckets_n);
-extern int HashTable_adjust(HashTable *table, int buckets_min);
-extern void pseudo_des(unsigned long *pleft, unsigned long *pright);
-extern Hashcode hash_string(char *s);
-
-extern int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order);
-
-/** Control whether to use hashing based on DES or simple
- * hashing. DES hashing is `more random' but much more expensive.
- */
-#define HASH_PSEUDO_DES 0
-
-/** Hash a long using a quick and dirty linear congruential random number generator.
- *  See `Numerical Recipes in C', Chapter 7, "An Even Quicker Generator".
- *
- * @param a value to hash
- * @return hashed input
- */
-static inline unsigned long lcrng_hash(unsigned long a){
-    return (1664525L * a + 1013904223L);
-}
-
-/** Hash an unsigned long.
- *
- * @param a input to hash
- * @return hashcode
- */
-static inline Hashcode hash_ul(unsigned long a){
-#if HASH_PSEUDO_DES
-    unsigned long left = a;
-    unsigned long right = 0L;
-    pseudo_des(&left, &right);
-    return right;
-#else
-    a = lcrng_hash(a);
-    a = lcrng_hash(a);
-    return a;
-#endif
-}
-
-/** Hash two unsigned longs together.
- *
- * @param a input to hash
- * @param b input to hash
- * @return hashcode
- */
-static inline Hashcode hash_2ul(unsigned long a, unsigned long b){
-#if HASH_PSEUDO_DES
-    unsigned long left = a;
-    unsigned long right = b;
-    pseudo_des(&left, &right);
-    return right;
-#else
-    a = lcrng_hash(a);
-    a ^= b;
-    a = lcrng_hash(a);
-    return a;
-#endif
-}
-
-/** Hash a hashcode and an unsigned long together.
- *
- * @param a input hashcode
- * @param b input to hash
- * @return hashcode
- */
-static inline Hashcode hash_hul(Hashcode a, unsigned long b){
-#if HASH_PSEUDO_DES
-    unsigned long left = a;
-    unsigned long right = b;
-    pseudo_des(&left, &right);
-    return right;
-#else
-    a ^= b;
-    a = lcrng_hash(a);
-    return a;
-#endif
-}
-
-/** Macro to declare variables for HashTable_for_each() to use.
- *
- * @param entry variable that is set to entries in the table
- */
-#define HashTable_for_decl(entry) \
-  HashTable *_var_table; \
-  HTBucket *_var_bucket; \
-  HTBucket *_var_end; \
-  HTEntry *_var_next; \
-  HTEntry *entry
-
-/** Macro to iterate over the entries in a hashtable.
- * Must be in a scope where HashTable_for_decl() has been used to declare
- * variables for it to use.
- * The variable 'entry' is iterated over entries in the table.
- * The code produced is syntactically a loop, so it must be followed by
- * a loop body, typically some statements in braces:
- * HashTable_for_each(entry, table){ ...loop body... }
- *
- * HashTable_for_each() and HashTable_for_decl() cannot be used for nested
- * loops as variables will clash.
- *
- * @note The simplest way to code a direct loop over the entries in a hashtable
- * is to use a loop over the buckets, with a nested loop over the entries
- * in a bucket. Using this approach in a macro means the macro contains
- * an opening brace, and calls to it must be followed by 2 braces!
- * To avoid this the code has been restructured so that it is a for loop.
- * So that statements could be used in the test expression of the for loop,
- * we have used the gcc statement expression extension ({ ... }).
- *
- * @param entry variable to iterate over the entries
- * @param table to iterate over (non-null)
- */
-#define HashTable_for_each(entry, table) \
-  _var_table = table; \
-  _var_bucket = _var_table->buckets; \
-  _var_end = _var_bucket + _var_table->buckets_n; \
-  for(entry=0, _var_next=0; \
-      ({ if(_var_next){ \
-             entry = _var_next; \
-             _var_next = entry->next; \
-          } else { \
-             while(_var_bucket < _var_end){ \
-                 entry = _var_bucket->head; \
-                 _var_bucket++; \
-                 if(entry){ \
-                      _var_next = entry->next; \
-                      break; \
-                 } \
-             } \
-          }; \
-         entry; }); \
-      entry = _var_next )
-
-/** Map a function over the entries in a table.
- * Mapping stops when the function returns a non-zero value.
- * Uses the gcc statement expression extension ({ ... }).
- *
- * @param table to map over
- * @param fn function to apply to entries
- * @param arg first argument to call the function with
- * @return 0 if fn always returned 0, first non-zero value otherwise
- */
-#define HashTable_map(table, fn, arg) \
-  ({ HashTable_for_decl(_var_entry); \
-    TableArg _var_arg = arg; \
-    int _var_value = 0; \
-    HashTable_for_each(_var_entry, table){ \
-        if((_var_value = fn(_var_arg, _var_table, _var_entry))) break; \
-    } \
-    _var_value; })
-
-/** Cast x to the type for a key or value in a hash table.
- * This avoids compiler warnings when using short integers
- * as keys or values (especially on 64-bit platforms).
- */
-#define HKEY(x) ((void*)(unsigned long)(x))
-
-/** Cast x from the type for a key or value in a hash table.
- * to an unsigned long. This avoids compiler warnings when using
- * short integers as keys or values (especially on 64-bit platforms).
- */
-#define HVAL(x) ((unsigned long)(x))
-
-#endif /* !_XEN_LIB_HASH_TABLE_H_ */
diff --git a/tools/lib/iostream.c b/tools/lib/iostream.c
deleted file mode 100644 (file)
index e998083..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#include "iostream.h"
-#include "sys_string.h"
-
-/** Print on a stream, like vfprintf().
- *
- * @param stream to print to
- * @param format for the print (as fprintf())
- * @param args arguments to print
- * @return result code from the print
- */
-int IOStream_vprint(IOStream *stream, const char *format, va_list args){
-  char buffer[1024];
-  int k = sizeof(buffer), n;
-
-  n = vsnprintf(buffer, k, (char*)format, args);
-  if(n < 0 || n > k ){
-      n = k;
-  }
-  n = IOStream_write(stream, buffer, n);
-  return n;
-}
-
-/** Print on a stream, like fprintf().
- *
- * @param stream to print to
- * @param format for the print (as fprintf())
- * @return result code from the print
- */
-int IOStream_print(IOStream *stream, const char *format, ...){
-  va_list args;
-  int result = -1;
-
-  va_start(args, format);
-  result = IOStream_vprint(stream, format, args);
-  va_end(args);
-  return result;
-}
diff --git a/tools/lib/iostream.h b/tools/lib/iostream.h
deleted file mode 100644 (file)
index 5dbe14a..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-#ifndef _XC_LINUX_SAVE_H_
-#define _XC_LINUX_SAVE_H_
-
-#include <stdarg.h>
-#include <stdint.h>
-#include <stddef.h>
-
-#ifdef __KERNEL__
-#include <linux/errno.h>
-#else
-#include <errno.h>
-#endif
-
-#include "allocate.h"
-
-/** End of input return value. */
-#define IOSTREAM_EOF -1
-
-/** An input/output abstraction.
- */
-typedef struct IOStream IOStream;
-
-/** Record of the functions to use for operations on an
- * IOStream implementation.
- */
-typedef struct IOMethods {
-    /** Read function.  Called with the user data, buffer to read into
-     * and number of bytes to read.  Must return number of bytes read
-     * on success, less than zero on error.
-     */
-    int (*read)(IOStream *stream, void *buf, size_t n);
-
-    /** Write function. Called with user data, buffer to write and
-     * number of bytes to write. Must return number of bytes written on
-     * success, less than zero otherwise.
-     */
-    int (*write)(IOStream *stream, const void *buf, size_t n);
-
-    int (*flush)(IOStream *s);
-
-    int (*error)(IOStream *s);
-
-    int (*close)(IOStream *s);
-
-    void (*free)(IOStream *s);
-
-    void (*lock)(IOStream *s);
-    void (*unlock)(IOStream *s);
-
-} IOMethods;
-
-/** Abstract i/o object.
- */
-struct IOStream {
-    /** Methods to use to implement operations. */
-    const IOMethods *methods;
-    /** Private state for the implementation. */
-    const void *data;
-    /** Flag indicating whether the stream is closed. */
-    int closed;
-    /** Number of bytes written. */
-    int written;
-    /** Number of bytes read. */
-    int read;
-};
-
-
-/** IOStream version of stdin. */
-extern IOStream *iostdin;
-
-/** IOStream version of stdout, */
-extern IOStream *iostdout;
-
-/** IOStream version of stderr. */
-extern IOStream *iostderr;
-
-extern int IOStream_print(IOStream *io, const char *format, ...);
-extern int IOStream_vprint(IOStream *io, const char *format, va_list args);
-
-/** Read from a stream.
- *
- * @param stream input
- * @param buf where to put input
- * @param n number of bytes to read
- * @return if ok, number of bytes read, otherwise negative error code
- */
-static inline int IOStream_read(IOStream *stream, void *buf, size_t n){
-    int result = 0;
-    if(stream->closed) goto exit;
-    if(!stream->methods || !stream->methods->read){
-        result = -EINVAL;
-        goto exit;
-    }
-    result = stream->methods->read(stream, buf, n);
-    if(result > 0){
-        stream->read += result;
-    }
-  exit:
-    return result;
-}
-
-/** Write to a stream.
- *
- * @param stream input
- * @param buf where to put input
- * @param n number of bytes to write
- * @return if ok, number of bytes read, otherwise negative error code
- */
-static inline int IOStream_write(IOStream *stream, const void *buf, size_t n){
-    int result = 0;
-    if(stream->closed) goto exit;
-    if(!stream->methods || !stream->methods->write){
-        result = -EINVAL;
-        goto exit;
-    }
-    result = stream->methods->write(stream, buf, n);
-    if(result > 0){
-        stream->written += result;
-    }
-  exit:
-    return result;
-}
-
-/** Flush the stream.
- *
- * @param stream stream
- * @return 0 on success, IOSTREAM_EOF otherwise
- */
-static inline int IOStream_flush(IOStream *stream){
-    int result = 0;
-    if(stream->closed){
-        result = IOSTREAM_EOF;
-    } else if(stream->methods->flush){
-        result = stream->methods->flush(stream);
-        if(result < 0) result = IOSTREAM_EOF;
-    }
-    return result;
-}
-
-/** Check whether the stream has an error.
- *
- * @param stream to check
- * @return 1 for error, 0 otherwise
- */
-static inline int IOStream_error(IOStream *stream){
-    int err = 0;
-    if(stream->methods && stream->methods->error){
-       err = stream->methods->error(stream);
-    }
-    return err;
-}
-
-/** Close the stream.
- *
- * @param stream to close
- * @return 1 for error, 0 otherwise
- */
-static inline int IOStream_close(IOStream *stream){
-    int err = 1;
-    if(stream->methods && stream->methods->close){
-        err = stream->methods->close(stream);
-    }
-    return err;
-}
-
-/** Test if the stream has been closed.
- *
- * @param stream to check
- * @return 1 if closed, 0 otherwise
- */
-static inline int IOStream_is_closed(IOStream *stream){
-  return stream->closed;
-}
-
-/** Free the memory used by the stream.
- *
- * @param stream to free
- */
-static inline void IOStream_free(IOStream *stream){
-  if(stream->methods && stream->methods->free){
-    stream->methods->free(stream);
-  }
-  *stream = (IOStream){};
-  deallocate(stream);
-}
-
-
-/** Print a character to a stream, like fputc().
- *
- * @param stream to print to
- * @param c character to print
- * @return result code from the print
- */
-static inline int IOStream_putc(IOStream *stream, int c){
-    int err;
-    unsigned char b = (unsigned char)c;
-    err = IOStream_write(stream, &b, 1);
-    if(err < 1){
-        err = IOSTREAM_EOF;
-    } else {
-        err = b;
-    }
-    return err;
-}
-
-/** Read from a stream, like fgetc().
- *
- * @param stream to read from
- * @return IOSTREAM_EOF on error, character read otherwise
- */
-static inline int IOStream_getc(IOStream *stream){
-    int err, rc;
-    unsigned char b;
-
-    err = IOStream_read(stream, &b, 1);
-    if(err < 1){
-        rc = IOSTREAM_EOF;
-    } else {
-        rc = b;
-    }
-    return rc;
-}
-
-/** Get number of bytes read.
- *
- * @param stream to get from
- * @return number of bytes read
- */
-static inline int IOStream_get_read(IOStream *stream){
-    return stream->read;
-}
-
-/** Get number of bytes written.
- *
- * @param stream to get from
- * @return number of bytes written
- */
-static inline int IOStream_get_written(IOStream *stream){
-    return stream->written;
-}
-
-
-#endif /* ! _XC_LINUX_SAVE_H_ */
diff --git a/tools/lib/kernel_stream.c b/tools/lib/kernel_stream.c
deleted file mode 100644 (file)
index 345b048..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/** @file
- * An IOStream implementation using printk() for output.
- * Input is not implemented.
- */
-#ifdef __KERNEL__
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-
-#include "kernel_stream.h"
-#include "allocate.h"
-
-/** Number of characters in the output buffer.
- * The kernel uses 1024 for printk, so that should suffice.
- */
-#define BUF_N 1024
-
-/** State for a kernel stream. */
-typedef struct KernelData {
-    /** Stream lock. We need a lock to serialize access to the stream. */
-    spinlock_t lock;
-    /** Saved flags for locking. */
-    unsigned long flags;
-    /** Size of the output buffer. */
-    int buf_n;
-    /** Output buffer. */
-    char buf[BUF_N];
-} KernelData;
-
-static int kernel_write(IOStream *s, const char *msg, int n);
-static void kernel_free(IOStream *s);
-static void kernel_stream_lock(IOStream *s);
-static void kernel_stream_unlock(IOStream *s);
-
-/** Methods for a kernel stream. Output only. */
-static const IOMethods kernel_methods = {
-  write:  kernel_write,
-  free:   kernel_free,
-  lock:   kernel_stream_lock,
-  unlock: kernel_stream_unlock,
-};
-
-/** Shared state for kernel streams.
- * All implementations write using printk, so we can use
- * shared state and avoid allocating it.
- */
-static const KernelData kernel_data = {
-  lock: SPIN_LOCK_UNLOCKED,
-  flags: 0,
-  buf_n: BUF_N,
-};
-
-/** Stream for kernel printk. */
-static IOStream iokernel = {
-    methods: &kernel_methods,
-    data:    &kernel_data,
-};
-
-/** Stream for kernel printk. */
-IOStream *iostdout = &iokernel;
-
-/** Stream for kernel printk. */
-IOStream *iostdin = &iokernel;
-
-/** Stream for kernel printk. */
-IOStream *iostderr = &iokernel;
-
-/** Get an output-only stream implementation using
- * printk(). The stream uses static storage, and must not be freed.
- *
- * @return kernel stream
- */
-IOStream get_stream_kernel(void){
-  return iokernel;
-}
-
-/** Obtain the lock on the stream state.
- *
- * @param kdata stream state
- */
-static inline void KernelData_lock(KernelData *kdata){
-  spin_lock_irqsave(&kdata->lock, kdata->flags);
-}
-
-/** Release the lock on the stream state.
- *
- * @param kdata stream state
- */
-static inline void KernelData_unlock(KernelData *kdata){
-  spin_unlock_irqrestore(&kdata->lock, kdata->flags);
-}
-
-/** Get the stream state.
- *
- * @param s kernel stream
- * @return stream state
- */
-static inline KernelData *get_kernel_data(IOStream *s){
-  return (KernelData*)s->data;
-}
-
-/** Obtain the lock on the stream state.
- *
- * @param s stream
- */
-void kernel_stream_lock(IOStream *s){
-    KernelData_lock(get_kernel_data(s));
-}
-
-/** Release the lock on the stream state.
- *
- * @param s stream
- */
-void kernel_stream_unlock(IOStream *s){
-    KernelData_unlock(get_kernel_data(s));
-}
-
-/** Write to a kernel stream.
- *
- * @param stream kernel stream
- * @param format print format
- * @param args print arguments
- * @return result of the print
- */
-static int kernel_write(IOStream *stream, const char *buf, int n){
-  KernelData *kdata = get_kernel_data(stream);
-  int k;
-  k = kdata->buf_n - 1;
-  if(n < k) k = n;
-  memcpy(kdata->buf, buf, k);
-  kdata->buf[k] = '\0'
-  printk(kdata->buf);
-  return k;
-}
-
-/** Free a kernel stream.
- * Frees the internal state of the stream.
- * Do not call this unless the stream was dynamically allocated.
- * Do not call this on a stream returned from get_stream_kernel().
- *
- * @param io stream to free
- */
-static void kernel_free(IOStream *io){
-  KernelData *kdata;
-  if(io == &iokernel) return;
-  kdata = get_kernel_data(io);
-  zero(kdata, sizeof(*kdata));
-  deallocate(kdata);
-}
-#endif /* __KERNEL__ */
-
-
-
-
diff --git a/tools/lib/kernel_stream.h b/tools/lib/kernel_stream.h
deleted file mode 100644 (file)
index be370f2..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _XEN_LIB_KERNEL_STREAM_H_
-#define _XEN_LIB_KERNEL_STREAM_H_
-
-#ifdef __KERNEL__
-#include "iostream.h"
-
-extern IOStream get_stream_kernel(void);
-#define get_stream_stdout get_stream_kernel
-
-#endif /* __KERNEL__ */
-#endif /* !_XEN_LIB_KERNEL_STREAM_H_ */
diff --git a/tools/lib/lexis.c b/tools/lib/lexis.c
deleted file mode 100644 (file)
index 26d2ec4..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or  (at your option) any later version. This library is 
- * distributed in the  hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-/** @file
- * Lexical analysis.
- */
-
-#include "sys_string.h"
-#include "lexis.h"
-#include <errno.h>
-
-/** Check if a value lies in a (closed) range.
- *
- * @param x value to test
- * @param lo low end of the range
- * @param hi high end of the range
- * @return 1 if x is in the interval [lo, hi], 0 otherwise
- */
-inline static int in_range(int x, int lo, int hi){
-    return (lo <= x) && (x <= hi);
-}
-
-/** Determine if a string is an (unsigned) decimal number.
- * 
- * @param s pointer to characters to test
- * @param n length of string
- * @return 1 if s is a decimal number, 0 otherwise.
- */
-int is_decimal_number(const char *s, int n){
-    int i;
-    if(n <= 0)return 0;
-    for(i = 0; i < n; i++){
-        if(!in_decimal_digit_class(s[i])) return 0;
-    }
-    return 1;
-}
-
-/** Determine if a string is a hex number.
- * Hex numbers are 0, or start with 0x or 0X followed
- * by a non-zero number of hex digits (0-9,a-f,A-F).
- * 
- * @param s pointer to characters to test
- * @param n length of string
- * @return 1 if s is a hex number, 0 otherwise.
- */
-int is_hex_number(const char *s, int n){
-    int i;
-    if(n <= 0) return 0;
-    if(n == 1){
-        return s[0]=='0';
-    }
-    if(n <= 3) return 0;
-    if(s[0] != '0' || (s[1] != 'x' && s[1] != 'X')) return 0;
-    for(i = 2; i < n; i++){
-        if(!in_hex_digit_class(s[i])) return 0;
-    }
-    return 1;
-}
-
-/** Test if a string matches a keyword.
- * The comparison is case-insensitive.
- * The comparison fails if either argument is null.
- *
- * @param s string
- * @param k keyword
- * @return 1 if they match, 0 otherwise
- */
-int is_keyword(const char *s, const char *k){
-  return s && k && !strcasecmp(s, k);
-}
-
-/** Test if a string matches a character.
- *
- * @param s string
- * @param c character (non-null)
- * @return 1 if s contains exactly c, 0 otherwise
- */
-int is_keychar(const char *s, char c){
-  return c && (s[0] == c) && !s[1];
-}
diff --git a/tools/lib/lexis.h b/tools/lib/lexis.h
deleted file mode 100644 (file)
index 7d8fe7b..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or  (at your option) any later version. This library is 
- * distributed in the  hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#ifndef _SP_LEXIS_H_
-#define _SP_LEXIS_H_
-
-#include "sys_string.h"
-#include "sys_ctype.h"
-
-/** @file
- * Lexical analysis.
- */
-
-/** Class of characters treated as space. */
-#define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 })
-
-/** Class of separator characters. */
-#define sep_class "{}()<>[]@!;"
-
-#define comment_class "#"
-
-/** Determine if a character is in a given class.
- * 
- * @param c character to test
- * @param s null-terminated string of characters in the class
- * @return 1 if c is in the class, 0 otherwise.
- */
-static inline int in_class(int c, const char *s){
-  return s && (strchr(s, c) != 0);
-}
-
-/** Determine if a character is in the space class.
- * 
- * @param c character to test
- * @return 1 if c is in the class, 0 otherwise.
- */
-static inline int in_space_class(int c){
-    return in_class(c, space_class);
-}
-
-static inline int in_comment_class(int c){
-    return in_class(c, comment_class);
-}
-
-/** Determine if a character is in the separator class.
- * Separator characters terminate tokens, and do not need space
- * to separate them.
- * 
- * @param c character to test
- * @return 1 if c is in the class, 0 otherwise.
- */
-static inline int in_sep_class(int c){
-    return in_class(c, sep_class);
-}
-
-/** Determine if a character is in the alpha class.
- * 
- * @param c character to test
- * @return 1 if c is in the class, 0 otherwise.
- */
-static inline int in_alpha_class(int c){
-    return isalpha(c);
-}
-
-/** Determine if a character is in the octal digit class.
- * 
- * @param c character to test
- * @return 1 if c is in the class, 0 otherwise.
- */
-static inline int in_octal_digit_class(int c){
-    return '0' <= c && c <= '7';
-}
-
-/** Determine if a character is in the decimal digit class.
- * 
- * @param c character to test
- * @return 1 if c is in the class, 0 otherwise.
- */
-static inline int in_decimal_digit_class(int c){
-    return isdigit(c);
-}
-
-/** Determine if a character is in the hex digit class.
- * 
- * @param c character to test
- * @return 1 if c is in the class, 0 otherwise.
- */
-static inline int in_hex_digit_class(int c){
-    return isdigit(c) || in_class(c, "abcdefABCDEF");
-}
-
-
-static inline int in_string_quote_class(int c){
-    return in_class(c, "'\"");
-}
-
-static inline int in_printable_class(int c){
-    return ('A' <= c && c <= 'Z')
-        || ('a' <= c && c <= 'z')
-        || ('0' <= c && c <= '9')
-        || in_class(c, "!$%&*+,-./:;<=>?@^_`{|}~");
-}
-
-extern int is_decimal_number(const char *s, int n);
-extern int is_hex_number(const char *s, int n);
-extern int is_keyword(const char *s, const char *k);
-extern int is_keychar(const char *s, char c);
-
-#endif /* !_SP_LEXIS_H_ */
diff --git a/tools/lib/lzi_stream.c b/tools/lib/lzi_stream.c
deleted file mode 100644 (file)
index 0f09734..0000000
+++ /dev/null
@@ -1,590 +0,0 @@
-/* $Id: lzi_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */
-#define __FILE_ID_INFO "$Id: lzi_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $"
-#include <what.h>
-static char __rcsid[] __attribute__((unused)) = WHAT_ID __FILE_ID_INFO;
-/*
- * Copyright (C) 2003 Hewlett-Packard Company.
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/** @file
- * An IOStream implementation using LZI to provide compression and decompression.
- * This is designed to provide compression without output latency.
- * Flushing an LZI stream flushes all pending data to the underlying stream.
- * This is essential for stream-based (e.g. networked) applications.
- *
- * A compressed data stream is a sequence of blocks.
- * Each block is the block size followed by the compressed data.
- * The last block has size zero.
- * Sizes are 4-byte unsigned in network order.
- *
- * This format allows compressed data to be read from a stream without reading
- * past the logical end of compressed data.
- *
- * @author Mike Wray <mike.wray@hpl.hp.com>
- */
-#ifndef __KERNEL__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-
-#include "zlib.h"
-
-#include "allocate.h"
-#include "lzi_stream.h"
-#include "file_stream.h"
-#include "marshal.h"
-
-#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] LZI>%s" fmt, __FUNCTION__, ##args)
-#define wprintf(fmt, args...) fprintf(stderr, "[WARN]  LZI>%s" fmt, __FUNCTION__, ##args)
-#define iprintf(fmt, args...) fprintf(stdout, "[INFO]  LZI>%s" fmt, __FUNCTION__, ##args)
-#define eprintf(fmt, args...) fprintf(stderr, "[ERROR] LZI>%s" fmt, __FUNCTION__, ##args)
-
-static int lzi_read(IOStream *s, void *buf, size_t size, size_t count);
-static int lzi_write(IOStream *s, const void *buf, size_t size, size_t count);
-static int lzi_print(IOStream *s, const char *msg, va_list args);
-static int lzi_getc(IOStream *s);
-static int lzi_error(IOStream *s);
-static int lzi_close(IOStream *s);
-static void lzi_free(IOStream *s);
-static int lzi_flush(IOStream *s);
-
-enum {
-    LZI_WRITE = 1,
-    LZI_READ = 2,
-};
-
-/** Methods used by a gzFile* IOStream. */
-static const IOMethods lzi_methods = {
-    read: lzi_read,
-    write: lzi_write,
-    print: lzi_print,
-    getc:  lzi_getc,
-    error: lzi_error,
-    close: lzi_close,
-    free:  lzi_free,
-    flush: lzi_flush,
-};
-
-#define BUFFER_SIZE (512 * 1024)
-
-typedef struct LZIState {
-    z_stream zstream;
-    void *inbuf;
-    uint32_t inbuf_size;
-    void *outbuf;
-    uint32_t outbuf_size;
-    /** Underlying stream for I/O. */
-    IOStream *io;
-    /** Flags. */
-    int flags;
-    /** Error indicator. */
-    int error;
-    int eof;
-    int plain_bytes;
-    int comp_bytes;
-    int zstream_initialized;
-    int flushed;
-} LZIState;
-
-static inline int LZIState_writeable(LZIState *s){
-    return (s->flags & LZI_WRITE) != 0;
-}
-
-static inline int LZIState_readable(LZIState *s){
-    return (s->flags & LZI_READ) != 0;
-}
-
-void LZIState_free(LZIState *z){
-    if(!z) return;
-    if(z->zstream_initialized){
-        if(LZIState_writeable(z)){
-            deflateEnd(&z->zstream);
-        } else if(LZIState_readable(z)){
-            inflateEnd(&z->zstream);
-        }
-    }
-    deallocate(z->inbuf);
-    deallocate(z->outbuf);
-    deallocate(z);
-}
-
-static int mode_flags(const char *mode, int *flags){
-    int err = 0;
-    int r=0, w=0;
-    if(!mode){
-        err = -EINVAL;
-        goto exit;
-    }
-    for(; *mode; mode++){
-        if(*mode == 'w') w = 1;
-        if(*mode == 'r') r = 1;
-    }
-    if(r + w != 1){
-        err = -EINVAL;
-        goto exit;
-    }
-    if(r) *flags |= LZI_READ;
-    if(w) *flags |= LZI_WRITE;
-  exit:
-    return err;
-}
-
-/** Get the stream state.
- * 
- * @param s lzi stream
- * @return stream state.
- */
-static inline LZIState * lzi_state(IOStream *io){
-    return io->data;
-}
-
-IOStream *lzi_stream_io(IOStream *io){
-    LZIState *s = lzi_state(io);
-    return s->io;
-}
-
-static inline void set_error(LZIState *s, int err){
-    if(err < 0 && !s->error){
-        s->error = err;
-    }
-}
-
-static int zerror(LZIState *s, int err){
-    if(err){
-        //dprintf("> err=%d\n", err);
-        if(err < 0) set_error(s, -EIO);
-    }
-    return s->error;
-}
-
-int lzi_stream_plain_bytes(IOStream *io){
-    LZIState *s = lzi_state(io);
-    return s->plain_bytes;
-}
-
-int lzi_stream_comp_bytes(IOStream *io){
-    LZIState *s = lzi_state(io);
-    return s->comp_bytes;
-}
-
-float lzi_stream_ratio(IOStream *io){
-    LZIState *s = lzi_state(io);
-    float ratio = 0.0;
-    if(s->comp_bytes){
-        ratio = ((float) s->comp_bytes)/((float) s->plain_bytes);
-    }
-    return ratio;
-}
-
-static int alloc(void **p, int n){
-    *p = allocate(n);
-    return (p ? 0 : -ENOMEM);
-}
-
-LZIState * LZIState_new(IOStream *io, int flags){
-    int err = -ENOMEM;
-    int zlevel = Z_BEST_SPEED; // Level 1 compression - fastest.
-    int zstrategy = Z_DEFAULT_STRATEGY;
-    int zwindow = MAX_WBITS;
-    int zmemory = 8;
-    LZIState *z = ALLOCATE(LZIState);
-
-    //dprintf(">\n");
-    if(!z) goto exit;
-    z->io = io;
-    z->flags = flags;
-
-    if(LZIState_writeable(z)){
-        z->outbuf_size = BUFFER_SIZE;
-        /* windowBits is passed < 0 to suppress zlib header */
-        err = deflateInit2(&z->zstream, zlevel, Z_DEFLATED, -zwindow, zmemory, zstrategy);
-        if (err != Z_OK) goto exit;
-        z->zstream_initialized = 1;
-        err = alloc(&z->outbuf, z->outbuf_size);
-        if(err) goto exit;
-        z->zstream.next_out = z->outbuf;
-        z->zstream.avail_out = z->outbuf_size;
-    } else {
-        z->inbuf_size = BUFFER_SIZE;
-        err = alloc(&z->inbuf, z->inbuf_size);
-        if(err) goto exit;
-        ///z->zstream.next_in  = z->inbuf;
-
-        /* windowBits is passed < 0 to tell that there is no zlib header.
-         * Note that in this case inflate *requires* an extra "dummy" byte
-         * after the compressed stream in order to complete decompression and
-         * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
-         * present after the compressed stream.
-         */
-        err = inflateInit2(&z->zstream, -zwindow);
-        if(err != Z_OK) goto exit;
-        z->zstream_initialized = 1;
-    }
-        
-  exit:
-    if(err){
-        LZIState_free(z);
-        z = NULL;
-    }
-    //dprintf("< z=%p\n", z);
-    return z;
-}
-
-int read_block(LZIState *s){
-    int err = 0, k = 0;
-    //dprintf(">\n");
-    if(s->eof) goto exit;
-    err = unmarshal_uint32(s->io, &k);
-    if(err) goto exit;
-    if(k > s->inbuf_size){
-        err = -EINVAL;
-        goto exit;
-    }
-    if(k){
-        err = unmarshal_bytes(s->io, s->inbuf, k);
-        if(err) goto exit;
-    } else {
-        s->eof = 1;
-    }        
-    s->zstream.avail_in = k;
-    s->zstream.next_in = s->inbuf;
-    s->comp_bytes += 4;
-    s->comp_bytes += k;
-  exit:
-    //dprintf("< err=%d\n", err);
-    return err;
-}
-
-int write_block(LZIState *s){
-    int err = 0;
-    int k = ((char*)s->zstream.next_out) - ((char*)s->outbuf);
-    int k2 = s->outbuf_size - s->zstream.avail_out;
-    //dprintf("> k=%d k2=%d\n", k, k2);
-    if(!k) goto exit;
-    err = marshal_uint32(s->io, k);
-    if(err) goto exit;
-    err = marshal_bytes(s->io, s->outbuf, k);
-    if(err) goto exit;
-    s->zstream.next_out = s->outbuf;
-    s->zstream.avail_out = s->outbuf_size;
-    s->comp_bytes += 4;
-    s->comp_bytes += k;
-  exit:
-    //dprintf("< err=%d\n", err);
-    return err;
-}
-
-int write_terminator(LZIState *s){
-    int err = 0;
-    char c = 0;
-    err = marshal_uint32(s->io, 1);
-    if(err) goto exit;
-    err = marshal_bytes(s->io, &c, 1);
-    if(err) goto exit;
-    err = marshal_uint32(s->io, 0);
-    if(err) goto exit;
-    s->comp_bytes += 9;
-  exit:
-    return err;
-}
-
-/** Write to the underlying stream using fwrite();
- *
- * @param io destination
- * @param buf data
- * @param size size of data elements
- * @param count number of data elements to write
- * @return number of data elements written
- */
-static int lzi_write(IOStream *io, const void *buf, size_t size, size_t count){
-    int err = 0;
-    int n = size * count;
-    LZIState *s = lzi_state(io);
-
-    //dprintf("> buf=%p size=%d count=%d n=%d\n", buf, size, count, n);
-    if(!LZIState_writeable(s)){
-        err = -EINVAL;
-        goto exit;
-    }
-    s->flushed = 0;
-    s->zstream.next_in = (void*)buf;
-    s->zstream.avail_in = n;
-    while(s->zstream.avail_in){
-        if(s->zstream.avail_out == 0){
-            err = write_block(s);
-            if(err) goto exit;
-        }
-        //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
-        //dprintf("> 1 deflate next_in=%p next_out=%p\n", s->zstream.next_in, s->zstream.next_out);
-        err = zerror(s, deflate(&s->zstream, Z_NO_FLUSH));
-        //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
-        //dprintf("> 2 deflate next_in=%p next_out=%p\n", s->zstream.next_in, s->zstream.next_out);
-        if(err) goto exit;
-    }
-    err = n;
-    s->plain_bytes += n;
-    if(size != 1) err /= size;
-  exit:
-    //dprintf("< err=%d\n", err);
-    return err;
-}
-
-
-/** Read from the underlying stream.
- *
- * @param io input
- * @param buf where to put input
- * @param size size of data elements
- * @param count number of data elements to read
- * @return number of data elements read
- */
-static int lzi_read(IOStream *io, void *buf, size_t size, size_t count){
-    int err, zerr;
-    int n = size * count;
-    LZIState *s = lzi_state(io);
-
-    //dprintf("> size=%d count=%d n=%d\n", size, count, n);
-    if(!LZIState_readable(s)){
-        err = -EINVAL;
-        goto exit;
-    }
-    s->zstream.next_out = buf;
-    s->zstream.avail_out = n;
-    while(s->zstream.avail_out){
-        if(s->zstream.avail_in == 0){
-            err = read_block(s);
-        }
-        //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
-        zerr = inflate(&s->zstream, Z_NO_FLUSH);
-        //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
-        if(zerr == Z_STREAM_END) break;
-        //dprintf("> zerr=%d\n", zerr);
-        err = zerror(s, zerr);
-        if(err) goto exit;
-    }
-    err = n - s->zstream.avail_out;
-    s->plain_bytes += err;
-    if(size != 1) err /= size;
-  exit:
-    set_error(s, err);
-    //dprintf("< err=%d\n", err);
-    return err;
-}
-
-/** Print to the underlying stream.
- * Returns 0 if the formatted output is too big for the internal buffer.
- *
- * @param io lzi stream
- * @param msg format to use
- * @param args arguments
- * @return result of the print
- */
-static int lzi_print(IOStream *io, const char *msg, va_list args){
-    char buf[1024];
-    int buf_n = sizeof(buf);
-    int n;
-    LZIState *s = lzi_state(io);
-    if(!LZIState_writeable(s)){
-        n = -EINVAL;
-        goto exit;
-    }
-    n = vsnprintf(buf, buf_n, (char*)msg, args);
-    if(n < 0) goto exit;
-    if(n > buf_n){
-        n = 0;
-    } else {
-        n = lzi_write(io, buf, 1, n);
-    }
-  exit:
-    return n;
-}
-
-/** Read a character from the underlying stream
- *
- * @param io lzi stream
- * @return character read, IOSTREAM_EOF on end of file (or error)
- */
-static int lzi_getc(IOStream *io){
-    int err;
-    char c;
-    err = lzi_read(io, &c, 1, 1);
-    if(err < 1) c = EOF;
-    err = (c==EOF ? IOSTREAM_EOF : c);
-    return err;
-}
-
-static int flush_output(LZIState *s, int mode){
-    int err = 0, zerr;
-    int done = 0;
-    int avail_out_old;
-    int count = 10;
-
-    //dprintf("> avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
-    if(s->flushed == 1 + mode) goto exit;
-    //s->zstream.avail_in = 0; /* should be zero already anyway */
-    for(;;){
-        // Write any available output.
-        if(done || s->zstream.avail_out == 0){
-            err = write_block(s);
-            if(err) goto exit;
-            if(done) break;
-        }
-        //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
-        avail_out_old = s->zstream.avail_out;
-        zerr = deflate(&s->zstream, mode);
-        err = zerror(s, zerr);
-        //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
-        //dprintf("> deflate=%d\n", err);
-        //done = (s->zstream.avail_out != 0);
-        //done = (s->zstream.avail_in == 0) && (s->zstream.avail_out == avail_out_old);
-        if(0 && mode == Z_FINISH){
-            done = (zerr ==  Z_STREAM_END);
-        } else {
-            done = (s->zstream.avail_in == 0)
-                //&& (s->zstream.avail_out == avail_out_old)
-                && (s->zstream.avail_out != 0);
-        }
-    }
-    s->flushed = 1 + mode;
-  exit:
-    //dprintf("< err=%d\n", err);
-    return err;
-}
-
-/** Flush any pending input to the underlying stream.
- *
- * @param s lzi stream
- * @return 0 on success, error code otherwise
- */
-static int lzi_flush(IOStream *io){
-    int err = 0;
-    LZIState *s = lzi_state(io);
-    //dprintf(">\n");
-    if(!LZIState_writeable(s)){
-        err = -EINVAL;
-        goto exit;
-    }
-    err = flush_output(s, Z_SYNC_FLUSH);
-    if(err) goto exit;
-    err = IOStream_flush(s->io);
-  exit:
-    set_error(s, err);
-    //dprintf("< err=%d\n", err);
-    return (err < 0 ? err : 0);
-}
-
-/** Check if a stream has an error.
- *
- * @param s lzi stream
- * @return code if has an error, 0 otherwise
- */
-static int lzi_error(IOStream *s){
-    int err = 0;
-    LZIState *state = lzi_state(s);
-    err = state->error;
-    if(err) goto exit;
-    err = IOStream_error(state->io);
-  exit:
-    return err;
-}
-
-/** Close an lzi stream.
- *
- * @param s lzi stream to close
- * @return result of the close
- */
-static int lzi_close(IOStream *io){
-    int err = 0;
-    LZIState *s = lzi_state(io);
-    if(LZIState_writeable(s)){
-        err = flush_output(s, Z_FINISH);
-        if(err) goto exit;
-        err = write_terminator(s);
-        if(err) goto exit;
-        err = IOStream_flush(s->io);
-    }   
-  exit:
-    err = IOStream_close(s->io);
-    set_error(s, err);
-    return err;
-}
-
-/** Free an lzi stream.
- *
- * @param s lzi stream
- */
-static void lzi_free(IOStream *s){
-    LZIState *state = lzi_state(s);
-    IOStream_free(state->io);
-    LZIState_free(state);
-    s->data = NULL;
-}
-
-/** Create an lzi stream for an IOStream.
- *
- * @param io stream to wrap
- * @return new IOStream using f for i/o
- */
-IOStream *lzi_stream_new(IOStream *io, const char *mode){
-    int err = -ENOMEM;
-    int flags = 0;
-    IOStream *zio = NULL;
-    LZIState *state = NULL;
-
-    zio = ALLOCATE(IOStream);
-    if(!zio) goto exit;
-    err = mode_flags(mode, &flags);
-    if(err) goto exit;
-    state = LZIState_new(io, flags);
-    if(!state) goto exit;
-    err = 0;
-    zio->data = state;
-    zio->methods = &lzi_methods;
-  exit:
-    if(err){
-        if(state) LZIState_free(state);
-        if(zio) deallocate(zio);
-        zio = NULL;
-    }
-    return zio;
-}
-
-/** IOStream version of fdopen().
- *
- * @param fd file descriptor
- * @param flags giving the mode to open in (as for fdopen())
- * @return new stream for the open file, or NULL if failed
- */
-IOStream *lzi_stream_fdopen(int fd, const char *mode){
-    int err = -ENOMEM;
-    IOStream *io = NULL, *zio = NULL;
-    io = file_stream_fdopen(fd, mode);
-    if(!io) goto exit;
-    zio = lzi_stream_new(io, mode);
-    if(!io) goto exit;
-    err = 0;
-  exit:
-    if(err){
-        IOStream_free(io);
-        IOStream_free(zio);
-        zio = NULL;
-    }
-    return zio;
-}
-#endif
diff --git a/tools/lib/lzi_stream.h b/tools/lib/lzi_stream.h
deleted file mode 100644 (file)
index 0ad4f8d..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#/* $Id: lzi_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */
-/*
- * Copyright (C) 2003 Hewlett-Packard Company.
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _SP_LZI_STREAM_H_
-#define _SP_LZI_STREAM_H_
-
-#ifndef __KERNEL__
-#include "iostream.h"
-
-extern IOStream *lzi_stream_new(IOStream *io, const char *mode);
-extern IOStream *lzi_stream_fopen(const char *file, const char *mode);
-extern IOStream *lzi_stream_fdopen(int fd, const char *mode);
-extern IOStream *lzi_stream_io(IOStream *zio);
-
-extern int lzi_stream_plain_bytes(IOStream *io);
-extern int lzi_stream_comp_bytes(IOStream *io);
-extern float lzi_stream_ratio(IOStream *io);
-
-#endif
-#endif /* !_SP_FILE_STREAM_H_ */
diff --git a/tools/lib/lzo_stream.c b/tools/lib/lzo_stream.c
deleted file mode 100644 (file)
index bf7c348..0000000
+++ /dev/null
@@ -1,596 +0,0 @@
-/* $Id: lzo_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */
-#define __FILE_ID_INFO "$Id: lzo_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $"
-#include <what.h>
-static char __rcsid[] __attribute__((unused)) = WHAT_ID __FILE_ID_INFO;
-/*
- * Copyright (C) 2003 Hewlett-Packard Company.
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/** @file
- * An IOStream implementation using LZO to provide compression and decompression.
- * This is designed to provide reasonable compression without output latency.
- * Flushing an LZO stream flushes all pending data to the underlying stream.
- * This is essential for stream-based (e.g. networked) applications.
- *
- * A compressed data stream is a sequence of blocks.
- * Each block except the last is the plain data size followed by the compressed data size
- * and the compressed data. The last block has plain data size zero and omits the rest.
- * Sizes are 4-byte unsigned in network order. If the compressed size is smaller than
- * the plain size the block data is compressed, otherwise it is plain (uncompressed).
- *
- * This format allows compressed data to be read from a stream without reading
- * past the logical end of compressed data.
- *
- * @author Mike Wray <mike.wray@hpl.hp.com>
- */
-#ifndef __KERNEL__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-
-#include "lzo1x.h"
-
-#include "allocate.h"
-#include "lzo_stream.h"
-#include "file_stream.h"
-#include "marshal.h"
-
-#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] LZO>%s" fmt, __FUNCTION__, ##args)
-#define wprintf(fmt, args...) fprintf(stderr, "[WARN]  LZO>%s" fmt, __FUNCTION__, ##args)
-#define iprintf(fmt, args...) fprintf(stdout, "[INFO]  LZO>%s" fmt, __FUNCTION__, ##args)
-#define eprintf(fmt, args...) fprintf(stderr, "[ERROR] LZO>%s" fmt, __FUNCTION__, ##args)
-
-static int lzo_read(IOStream *s, void *buf, size_t size, size_t count);
-static int lzo_write(IOStream *s, const void *buf, size_t size, size_t count);
-static int lzo_print(IOStream *s, const char *msg, va_list args);
-static int lzo_getc(IOStream *s);
-static int lzo_error(IOStream *s);
-static int lzo_close(IOStream *s);
-static void lzo_free(IOStream *s);
-static int lzo_flush(IOStream *s);
-
-enum {
-    LZO_WRITE = 1,
-    LZO_READ = 2,
-};
-
-/** Methods used by a gzFile* IOStream. */
-static const IOMethods lzo_methods = {
-    read: lzo_read,
-    write: lzo_write,
-    print: lzo_print,
-    getc:  lzo_getc,
-    error: lzo_error,
-    close: lzo_close,
-    free:  lzo_free,
-    flush: lzo_flush,
-};
-
-//#define PLAIN_SIZE (64 * 1024)
-//#define PLAIN_SIZE (128 * 1024)
-#define PLAIN_SIZE (512 * 1024)
-
-//#define NOCOMPRESS
-
-typedef struct LZOState {
-    /** Flags. */
-    int flags;
-    /** Error indicator. */
-    int error;
-    /** Underlying stream for I/O. */
-    IOStream *io;
-    /** Working memory (only needed for compression, not decompression). */
-    lzo_byte *memory;
-    /** Buffer for plain (uncompressed) data. */
-    lzo_byte *plain;
-    /** Size of the plain buffer. */
-    lzo_uint plain_size;
-    /** Pointer into the plain buffer. */
-    lzo_byte *plain_ptr;
-    /** Number of bytes of plain data available. */
-    lzo_uint plain_n;
-    /** Buffer for compressed data. */
-    lzo_byte *comp;
-    /** Size of the compressed buffer. */
-    lzo_uint comp_size;
-
-    int plain_bytes;
-    int comp_bytes;
-} LZOState;
-
-void LZOState_free(LZOState *z){
-    if(!z) return;
-    deallocate(z->memory);
-    deallocate(z->plain);
-    deallocate(z->comp);
-    deallocate(z);
-}
-
-/** Maximum size of compressed data for the given plain data size.
- *
- * @param plain_size size of plain data
- * @return maximum size of compressed data
- */
-static int comp_size(int plain_size){
-    return plain_size + (plain_size / 64) + 16 + 3;
-}
-
-static int mode_flags(const char *mode, int *flags){
-    int err = 0;
-    int r=0, w=0;
-    if(!mode){
-        err = -EINVAL;
-        goto exit;
-    }
-    for(; *mode; mode++){
-        if(*mode == 'w') w = 1;
-        if(*mode == 'r') r = 1;
-    }
-    if(r + w != 1){
-        err = -EINVAL;
-        goto exit;
-    }
-    if(r) *flags |= LZO_READ;
-    if(w) *flags |= LZO_WRITE;
-  exit:
-    return err;
-}
-
-/** Get the stream state.
- * 
- * @param s lzo stream
- * @return stream state.
- */
-static inline LZOState * lzo_state(IOStream *s){
-    return s->data;
-}
-
-IOStream *lzo_stream_io(IOStream *s){
-    LZOState *state = lzo_state(s);
-    return state->io;
-}
-
-static inline void set_error(LZOState *state, int err){
-    if(err < 0 && !state->error){
-        state->error = err;
-    }
-}
-
-int lzo_stream_plain_bytes(IOStream *s){
-    LZOState *state = lzo_state(s);
-    return state->plain_bytes;
-}
-
-int lzo_stream_comp_bytes(IOStream *s){
-    LZOState *state = lzo_state(s);
-    return state->comp_bytes;
-}
-
-float lzo_stream_ratio(IOStream *s){
-    LZOState *state = lzo_state(s);
-    float ratio = 0.0;
-    if(state->comp_bytes){
-        ratio = ((float) state->comp_bytes)/((float) state->plain_bytes);
-    }
-    return ratio;
-}
-
-static inline int LZOState_writeable(LZOState *state){
-    return (state->flags & LZO_WRITE) != 0;
-}
-
-static inline int LZOState_readable(LZOState *state){
-    return (state->flags & LZO_READ) != 0;
-}
-
-LZOState * LZOState_new(IOStream *io, int flags){
-    int err = -ENOMEM;
-    LZOState *z = ALLOCATE(LZOState);
-    //dprintf(">\n");
-    if(!z) goto exit;
-    z->io = io;
-    z->flags = flags;
-    if(LZOState_writeable(z)){
-        z->memory = allocate(LZO1X_1_MEM_COMPRESS);
-        if(!z->memory) goto exit;
-    }
-    z->plain_size = PLAIN_SIZE;
-    z->plain = allocate(z->plain_size);
-    if(!z->plain) goto exit;
-    z->plain_ptr = z->plain;
-    z->comp_size = comp_size(z->plain_size);
-    z->comp = allocate(z->comp_size);
-    if(!z->comp) goto exit;
-    err = 0;
-  exit:
-    if(err){
-        LZOState_free(z);
-        z = NULL;
-    }
-    //dprintf("< z=%p\n", z);
-    return z;
-}
-
-static int lzo_compress(LZOState *state){
-    int err = 0;
-    int k, comp_n;
-    //dprintf(">\n");
-    //dprintf(">plain=%p plain_n=%d comp=%p memory=%p\n", state->plain, state->plain_n, state->comp, state->memory);
-    // Compress the plain buffer.
-    err = lzo1x_1_compress(state->plain, state->plain_n,
-                           state->comp, &comp_n,
-                           state->memory);
-    //dprintf("> err=%d plain_n=%d comp_n=%d\n", err, state->plain_n, comp_n);
-    // Write plain size, compressed size.
-    err = marshal_uint32(state->io, state->plain_n);
-    if(err) goto exit;
-    err = marshal_uint32(state->io, comp_n);
-    if(err) goto exit;
-    //dprintf("> write data...\n");
-    // Write the smaller of the compressed and plain data.
-    if(state->plain_n < comp_n){
-        k = state->plain_n;
-        err = marshal_bytes(state->io, state->plain, state->plain_n);
-    } else {
-        k = comp_n;
-        err = marshal_bytes(state->io, state->comp, comp_n);
-    }
-    if(err) goto exit;
-    // Total output bytes.
-    k+= 8;
-    //dprintf("> wrote %d bytes\n", k);
-    state->plain_bytes += state->plain_n;
-    state->comp_bytes += k;
-    //dprintf("> plain=%d, comp=%d, ratio=%3.2f\n",
-    //        state->plain_bytes, state->comp_bytes,
-    //        ((float)state->comp_bytes)/((float)state->plain_bytes));
-    // Reset the plain buffer.
-    state->plain_ptr = state->plain;
-    state->plain_n = 0;
-    err = k;
-  exit:
-    //dprintf("< err=%d\n", err);
-    return err;
-}
-
-static int lzo_decompress(LZOState *state){
-    int plain_n, comp_n;
-    int err, k;
-    //dprintf(">\n");
-    err = unmarshal_uint32(state->io, &plain_n);
-    //dprintf("> err=%d plain_n=%d\n", err, plain_n);
-    if(err) goto exit;
-    state->comp_bytes += 4;
-    if(plain_n == 0) goto exit;
-    err = unmarshal_uint32(state->io, &comp_n);
-    //dprintf("> err=%d comp_n=%d\n", err, comp_n);
-    if(err) goto exit;
-    state->comp_bytes += 4;
-    if(plain_n > state->plain_size){
-        err = -EINVAL;
-        goto exit;
-    }
-    if(comp_n > plain_n){
-        //dprintf("> reading plain data %d...\n", plain_n);
-        k = plain_n;
-        err = unmarshal_bytes(state->io, state->plain, plain_n);
-        state->plain_n = plain_n;
-    } else {
-        //dprintf("> reading comp data %d...\n", comp_n);
-        k = comp_n;
-        err = unmarshal_bytes(state->io, state->comp, comp_n);
-        //dprintf("> decompress comp_n=%d\n", comp_n);
-        err = lzo1x_decompress(state->comp, comp_n,
-                               state->plain, &state->plain_n,
-                               state->memory);
-        //dprintf("> err=%d plain=%d state->plain_n=%d\n", err, plain_n, state->plain_n);
-        if(err != LZO_E_OK || state->plain_n != plain_n){
-            // Bad. Corrupted input.
-            err = -EINVAL;
-            eprintf("> Corrupted!\n");
-            goto exit;
-        }
-    }
-    state->comp_bytes += k;
-    state->plain_bytes += state->plain_n;
-    state->plain_ptr = state->plain;
-    err = k;
-  exit:
-    //dprintf("< err=%d\n", err);
-    return err;
-}
-
-/** Write to the underlying stream using fwrite();
- *
- * @param stream destination
- * @param buf data
- * @param size size of data elements
- * @param count number of data elements to write
- * @return number of data elements written
- */
-static int lzo_write(IOStream *s, const void *buf, size_t size, size_t count){
-    int err = 0;
-    int n = size * count; // Total number of bytes to write.
-    int chunk;            // Size of chunk to write.
-    int remaining;        // Number of bytes remaining to write.
-    int space;            // Amount of space left in plain buffer.
-    LZOState *state = lzo_state(s);
-#ifdef NOCOMPRESS
-    //dprintf("> buf=%p size=%d count=%d\n", buf, size, count);
-    err = IOStream_write(state->io, buf, size, count);
-    //dprintf("< err=%d\n", err);
-#else
-    //dprintf("> buf=%p size=%d count=%d n=%d\n", buf, size, count, n);
-    remaining = n;
-    space = state->plain_size - state->plain_n;
-    //dprintf("> plain=%p plain_ptr=%p plain_n=%d space=%d\n",
-    //        state->plain, state->plain_ptr, state->plain_n, space);
-    while(remaining){
-        chunk = remaining;
-        if(chunk > space) chunk = space;
-        //dprintf("> memcpy %p %p %d\n", state->plain_ptr, buf, chunk);
-        memcpy(state->plain_ptr, buf, chunk);
-        remaining -= chunk;
-        space -= chunk;
-        state->plain_ptr += chunk;
-        state->plain_n += chunk;
-        if(space == 0){
-            // Input buffer is full. Compress and write it.
-            err = lzo_compress(state);
-            if(err < 0) goto exit;
-            space = state->plain_size - state->plain_n;
-        }
-    }
-    err = (size > 1 ? n / size : n);
-  exit:
-    set_error(state, err);
-#endif
-    return err;
-}
-
-
-/** Read from the underlying stream.
- *
- * @param stream input
- * @param buf where to put input
- * @param size size of data elements
- * @param count number of data elements to read
- * @return number of data elements read
- */
-static int lzo_read(IOStream *s, void *buf, size_t size, size_t count){
-    int err = 0;
-    int k = 0;                     // Number of (plain) bytes read.
-    int remaining = size * count;  // Number of bytes remaining to read.
-    int chunk;                     // Size of chunk to read.
-    LZOState *state = lzo_state(s);
-#ifdef NOCOMPRESS
-    //dprintf("> buf=%p size=%d count=%d\n", buf, size, count);
-    err = IOStream_read(state->io, buf, size, count);
-    //dprintf("< err=%d\n", err);
-#else
-    if(!(state->flags & LZO_READ)){
-        err = -EINVAL;
-        goto exit;
-    }
-    while(remaining){
-        if(state->plain_n == 0){
-            // No more plain input, decompress some more.
-            err = lzo_decompress(state);
-            if(err < 0) goto exit;
-            // Stop reading if there is no more input.
-            if(err == 0 || state->plain_n == 0) break;
-        }
-        chunk = remaining;
-        if(chunk > state->plain_n) chunk = state->plain_n;
-        memcpy(buf, state->plain_ptr, chunk);
-        k += chunk;
-        buf += chunk;
-        state->plain_ptr += chunk;
-        state->plain_n -= chunk;
-        remaining -= chunk;
-    }
-    err = k;
-  exit:
-    set_error(state, err);
-#endif
-    return err;
-}
-
-/** Print to the underlying stream.
- * Returns 0 if the formatted output is too big for the internal buffer.
- *
- * @param s lzo stream
- * @param msg format to use
- * @param args arguments
- * @return result of the print
- */
-static int lzo_print(IOStream *s, const char *msg, va_list args){
-    char buf[1024];
-    int buf_n = sizeof(buf);
-    int n;
-    LZOState *state = lzo_state(s);
-    if(!LZOState_writeable(state)){
-        n = -EINVAL;
-        goto exit;
-    }
-    n = vsnprintf(buf, buf_n, (char*)msg, args);
-    if(n < 0) goto exit;
-    if(n > buf_n){
-        n = 0;
-    } else {
-        n = lzo_write(s, buf, 1, n);
-    }
-  exit:
-    return n;
-}
-
-/** Read a character from the underlying stream
- *
- * @param s lzo stream
- * @return character read, IOSTREAM_EOF on end of file (or error)
- */
-static int lzo_getc(IOStream *s){
-    int err;
-    char c;
-    err = lzo_read(s, &c, 1, 1);
-    if(err < 1) c = EOF;
-    err = (c==EOF ? IOSTREAM_EOF : c);
-    return err;
-}
-
-/** Flush any pending input to the underlying stream.
- *
- * @param s lzo stream
- * @return 0 on success, error code otherwise
- */
-static int lzo_flush(IOStream *s){
-    int err = 0;
-    LZOState *state = lzo_state(s);
-    //dprintf(">\n");
-#ifdef NOCOMPRESS
-    err = IOStream_flush(state->io);
-#else    
-    if(!LZOState_writeable(state)){
-        err = -EINVAL;
-        goto exit;
-    }
-    if(state->plain_n){
-        err = lzo_compress(state);
-        if(err < 0) goto exit;
-    }
-    err = IOStream_flush(state->io);
-  exit:
-    set_error(state, err);
-#endif
-    //dprintf("< err=%d\n", err);
-    return (err < 0 ? err : 0);
-}
-
-/** Check if a stream has an error.
- *
- * @param s lzo stream
- * @return code if has an error, 0 otherwise
- */
-static int lzo_error(IOStream *s){
-    int err = 0;
-    LZOState *state = lzo_state(s);
-    err = state->error;
-    if(err) goto exit;
-    err = IOStream_error(state->io);
-  exit:
-    return err;
-}
-
-int lzo_stream_finish(IOStream *s){
-    int err = 0;
-    LZOState *state = lzo_state(s);
-    if(!LZOState_writeable(state)){
-        err = -EINVAL;
-        goto exit;
-    }
-    err = lzo_flush(s);
-    if(err < 0) goto exit;
-    err = marshal_int32(state->io, 0);
-  exit:
-    return err;
-}        
-
-/** Close an lzo stream.
- *
- * @param s lzo stream to close
- * @return result of the close
- */
-static int lzo_close(IOStream *s){
-    int err = 0;
-    LZOState *state = lzo_state(s);
-#ifdef NOCOMPRESS
-    err = IOStream_close(state->io);
-#else    
-    if(LZOState_writeable(state)){
-        err = lzo_stream_finish(s);
-    }        
-    err = IOStream_close(state->io);
-    set_error(state, err);
-#endif
-    return err;
-}
-
-/** Free an lzo stream.
- *
- * @param s lzo stream
- */
-static void lzo_free(IOStream *s){
-    LZOState *state = lzo_state(s);
-    IOStream_free(state->io);
-    LZOState_free(state);
-    s->data = NULL;
-}
-
-/** Create an lzo stream for an IOStream.
- *
- * @param io stream to wrap
- * @return new IOStream using f for i/o
- */
-IOStream *lzo_stream_new(IOStream *io, const char *mode){
-    int err = -ENOMEM;
-    int flags = 0;
-    IOStream *zio = NULL;
-    LZOState *state = NULL;
-
-    zio = ALLOCATE(IOStream);
-    if(!zio) goto exit;
-    err = mode_flags(mode, &flags);
-    if(err) goto exit;
-    state = LZOState_new(io, flags);
-    if(!state) goto exit;
-    err = 0;
-    zio->data = state;
-    zio->methods = &lzo_methods;
-  exit:
-    if(err){
-        if(state) LZOState_free(state);
-        if(zio) deallocate(zio);
-        zio = NULL;
-    }
-    return zio;
-}
-
-/** IOStream version of fdopen().
- *
- * @param fd file descriptor
- * @param flags giving the mode to open in (as for fdopen())
- * @return new stream for the open file, or NULL if failed
- */
-IOStream *lzo_stream_fdopen(int fd, const char *mode){
-    int err = -ENOMEM;
-    IOStream *io = NULL, *zio = NULL;
-    io = file_stream_fdopen(fd, mode);
-    if(!io) goto exit;
-    zio = lzo_stream_new(io, mode);
-    if(!io) goto exit;
-    err = 0;
-  exit:
-    if(err){
-        IOStream_free(io);
-        IOStream_free(zio);
-        zio = NULL;
-    }
-    return zio;
-}
-#endif
diff --git a/tools/lib/lzo_stream.h b/tools/lib/lzo_stream.h
deleted file mode 100644 (file)
index 493da7b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#/* $Id: lzo_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */
-/*
- * Copyright (C) 2003 Hewlett-Packard Company.
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _SP_LZO_STREAM_H_
-#define _SP_LZO_STREAM_H_
-
-#ifndef __KERNEL__
-#include "iostream.h"
-
-extern IOStream *lzo_stream_new(IOStream *io, const char *mode);
-extern IOStream *lzo_stream_fopen(const char *file, const char *mode);
-extern IOStream *lzo_stream_fdopen(int fd, const char *mode);
-extern IOStream *lzo_stream_io(IOStream *zio);
-
-extern int lzo_stream_plain_bytes(IOStream *io);
-extern int lzo_stream_comp_bytes(IOStream *io);
-extern float lzo_stream_ratio(IOStream *io);
-
-#endif
-#endif /* !_SP_FILE_STREAM_H_ */
diff --git a/tools/lib/marshal.c b/tools/lib/marshal.c
deleted file mode 100644 (file)
index 21691d4..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-#include <errno.h>
-#include "sys_net.h"
-#include "allocate.h"
-#include "marshal.h"
-
-#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
-#define wprintf(fmt, args...) IOStream_print(iostderr, "[WARN]  %s" fmt, __FUNCTION__, ##args)
-#define iprintf(fmt, args...) IOStream_print(iostdout, "[INFO]  %s" fmt, __FUNCTION__, ##args)
-#define eprintf(fmt, args...) IOStream_print(iostderr, "[ERROR] %s" fmt, __FUNCTION__, ##args)
-
-
-#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof((ary)[0]))
-
-/* Messages are coded as msgid followed by message fields.
- * Initial message on any channel is hello - so can check version
- * compatibility.
- *
- * char* -> uint16_t:n <n bytes>
- * ints/uints go as suitable number of bytes (e.g. uint16_t is 2 bytes).
- * optional fields go as '1' <val> or '0' (the 0/1 is 1 byte).
- * lists go as ('1' <elt>)* '0'
- */
-
-int marshal_flush(IOStream *io){
-    int err  = 0;
-    err = IOStream_flush(io);
-    return err;
-}
-
-int marshal_bytes(IOStream *io, void *s, uint32_t s_n){
-    int err = 0;
-    int n;
-    n = IOStream_write(io, s, s_n);
-    if(n < 0){
-        err = n;
-    } else if (n < s_n){
-        wprintf("> Wanted %d, got %d\n", s_n, n);
-        err = -EIO;
-    }
-    return err;
-}
-
-int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n){
-    int err = 0;
-    int n;
-    //dprintf("> s_n=%d\n", s_n);
-    n = IOStream_read(io, s, s_n);
-    //dprintf("> n=%d\n", n);
-    if(n < 0){
-        err = n;
-    } else if(n < s_n){
-        wprintf("> Wanted %d, got %d\n", s_n, n);
-        err = -EIO;
-    }
-    //dprintf("< err=%d\n", err);
-    return err;
-}
-
-int marshal_uint8(IOStream *io, uint8_t x){
-    return marshal_bytes(io, &x, sizeof(x));
-}
-
-int unmarshal_uint8(IOStream *io, uint8_t *x){
-    return unmarshal_bytes(io, x, sizeof(*x));
-}
-
-int marshal_uint16(IOStream *io, uint16_t x){
-    x = htons(x);
-    return marshal_bytes(io, &x, sizeof(x));
-}
-
-int unmarshal_uint16(IOStream *io, uint16_t *x){
-    int err = 0;
-    err = unmarshal_bytes(io, x, sizeof(*x));
-    *x = ntohs(*x);
-    return err;
-}
-
-int marshal_int32(IOStream *io, int32_t x){
-    int err = 0;
-    //dprintf("> x=%d\n", x);
-    x = htonl(x);
-    err = marshal_bytes(io, &x, sizeof(x));
-    //dprintf("< err=%d\n", err);
-    return err;
-}
-
-int unmarshal_int32(IOStream *io, int32_t *x){
-    int err = 0;
-    //dprintf(">\n");
-    err = unmarshal_bytes(io, x, sizeof(*x));
-    *x = ntohl(*x);
-    //dprintf("< err=%d x=%d\n", err, *x);
-    return err;
-}
-
-int marshal_uint32(IOStream *io, uint32_t x){
-    int err = 0;
-    //dprintf("> x=%u\n", x);
-    x = htonl(x);
-    err = marshal_bytes(io, &x, sizeof(x));
-    //dprintf("< err=%d\n", err);
-    return err;
-}
-
-int unmarshal_uint32(IOStream *io, uint32_t *x){
-    int err = 0;
-    //dprintf(">\n");
-    err = unmarshal_bytes(io, x, sizeof(*x));
-    *x = ntohl(*x);
-    //dprintf("< err=%d x=%u\n", err, *x);
-    return err;
-}
-
-int marshal_uint64(IOStream *io, uint64_t x){
-    int err;
-    err = marshal_uint32(io, (uint32_t) ((x >> 32) & 0xffffffff));
-    if(err) goto exit;
-    err = marshal_uint32(io, (uint32_t) ( x        & 0xffffffff));
-  exit:
-    return err;
-}
-
-int unmarshal_uint64(IOStream *io, uint64_t *x){
-    int err = 0;
-    uint32_t hi, lo;
-    err = unmarshal_uint32(io, &hi);
-    if(err) goto exit;
-    err = unmarshal_uint32(io, &lo);
-    *x = (((uint64_t) hi) << 32) | lo;
-  exit:
-    return err;
-}
-
-int marshal_net16(IOStream *io, net16_t x){
-    return marshal_bytes(io, &x, sizeof(x));
-}
-
-int unmarshal_net16(IOStream *io, net16_t *x){
-    int err = 0;
-    err = unmarshal_bytes(io, x, sizeof(*x));
-    return err;
-}
-
-int marshal_net32(IOStream *io, net32_t x){
-    return marshal_bytes(io, &x, sizeof(x));
-}
-
-int unmarshal_net32(IOStream *io, net32_t *x){
-    int err = 0;
-    err = unmarshal_bytes(io, x, sizeof(*x));
-    return err;
-}
-
-int marshal_string(IOStream *io, char *s, uint32_t s_n){
-    int err;
-    //dprintf("> s=%s\n", s);
-    err = marshal_uint32(io, s_n);
-    if(err) goto exit;
-    err = marshal_bytes(io, s, s_n);
-  exit:
-    //dprintf("< err=%d\n", err);
-    return err;
-}
-
-int unmarshal_string(IOStream *io, char *s, uint32_t s_n){
-    int err = 0, val_n = 0;
-    //dprintf(">\n");
-    err = unmarshal_uint32(io, &val_n);
-    if(err) goto exit;
-    if(val_n >= s_n){
-        err = -EINVAL;
-        goto exit;
-    }
-    err = unmarshal_bytes(io, s, val_n);
-    if(err) goto exit;
-    s[val_n] = '\0';
-  exit:
-    //dprintf("< err=%d s=%s\n", err, s);
-    return err;
-}
-
-int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n){
-    int err = 0, val_n = 0;
-    char *val = NULL;
-    //dprintf(">\n");
-    err = unmarshal_uint32(io, &val_n);
-    if(err) goto exit;
-    val = allocate(val_n + 1);
-    if(!val){
-        err = -ENOMEM;
-        goto exit;
-    }
-    err = unmarshal_bytes(io, val, val_n);
-    if(err) goto exit;
-    val[val_n] = '\0';
-  exit:
-    if(err){
-        if(val) deallocate(val);
-        val = NULL;
-        val_n = 0;
-    }
-    *s = val;
-    if(s_n) *s_n = val_n;
-    //dprintf("< err=%d s=%s\n", err, *s);
-    return err;
-}
diff --git a/tools/lib/marshal.h b/tools/lib/marshal.h
deleted file mode 100644 (file)
index 9a9d465..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* $Id: marshal.h,v 1.1 2003/10/17 15:48:43 mjw Exp $ */
-#ifndef _SP_MARSHAL_H_
-#define _SP_MARSHAL_H_
-
-#include "iostream.h"
-
-/** A 16-bit uint in network order, e.g. a port number. */
-typedef uint16_t net16_t;
-
-/** A 32-bit uint in network order, e.g. an IP address. */
-typedef uint32_t net32_t;
-
-extern int marshal_flush(IOStream *io);
-
-extern int marshal_bytes(IOStream *io, void *s, uint32_t s_n);
-extern int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n);
-
-extern int marshal_uint8(IOStream *io, uint8_t x);
-extern int unmarshal_uint8(IOStream *io, uint8_t *x);
-
-extern int marshal_uint16(IOStream *io, uint16_t x);
-extern int unmarshal_uint16(IOStream *io, uint16_t *x);
-
-extern int marshal_uint32(IOStream *io, uint32_t x);
-extern int unmarshal_uint32(IOStream *io, uint32_t *x);
-
-extern int marshal_int32(IOStream *io, int32_t x);
-extern int unmarshal_int32(IOStream *io, int32_t *x);
-
-extern int marshal_uint64(IOStream *io, uint64_t x);
-extern int unmarshal_uint64(IOStream *io, uint64_t *x);
-
-extern int marshal_net16(IOStream *io, net16_t x);
-extern int unmarshal_net16(IOStream *io, net16_t *x);
-
-extern int marshal_net32(IOStream *io, net32_t x);
-extern int unmarshal_net32(IOStream *io, net32_t *x);
-
-extern int marshal_string(IOStream *io, char *s, uint32_t s_n);
-extern int unmarshal_string(IOStream *io, char *s, uint32_t s_n);
-extern int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n);
-
-#endif /* ! _SP_MARSHAL_H_ */
diff --git a/tools/lib/socket_stream.c b/tools/lib/socket_stream.c
deleted file mode 100644 (file)
index cfa6e3a..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-/* $Id: socket_stream.c,v 1.9 2004/03/05 14:45:34 mjw Exp $ */
-/*
- * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/** @file
- * An IOStream implementation using sockets.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include "allocate.h"
-#include "socket_stream.h"
-
-#define MODULE_NAME "sock"
-#define DEBUG 0
-//#undef DEBUG
-#include "debug.h"
-
-static int socket_read(IOStream *s, void *buf, size_t n);
-static int socket_write(IOStream *s, const void *buf, size_t n);
-static int socket_error(IOStream *s);
-static int socket_close(IOStream *s);
-static void socket_free(IOStream *s);
-static int socket_flush(IOStream *s);
-
-/** Methods used by a socket IOStream. */
-static const IOMethods socket_methods = {
-    read:  socket_read,
-    write: socket_write,
-    error: socket_error,
-    close: socket_close,
-    free:  socket_free,
-    flush: socket_flush,
-};
-
-/** Get the socket data.
- * 
- * @param io socket stream
- * @return data
- */
-static inline SocketData * socket_data(IOStream *io){
-    return (SocketData *)io->data;
-}
-
-/** Test if a stream is a socket stream.
- *
- * @param io stream
- * @return 0 if a socket stream, -EINVAL if not
- */
-int socket_stream_check(IOStream *io){
-    return (io && io->methods == &socket_methods ? 0 : -EINVAL);
-}
-
-/** Get the data for a socket stream.
- *
- * @param io stream
- * @param data return value for the data
- * @return 0 if a socket stream, -EINVAL if not
- */
-int socket_stream_data(IOStream *io, SocketData **data){
-    int err = socket_stream_check(io);
-    if(err){
-        *data = NULL;
-    } else {
-        *data = socket_data(io);
-    }
-    return err;
-}
-
-/** Set the destination address for a socket stream.
- *
- * @param io stream
- * @param addr address
- * @return 0 if a socket stream, -EINVAL if not
- */
-int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr){
-    int err = 0;
-    SocketData *data = NULL;
-    err = socket_stream_data(io, &data);
-    if(!err){
-        data->daddr = *addr;
-    }
-    return err;
-}
-
-/** Set the send flags for a socket stream.
- *
- * @param io stream
- * @param flags flags
- * @return 0 if a socket stream, -EINVAL if not
- */
-int socket_stream_set_flags(IOStream *io, int flags){
-    int err = 0;
-    SocketData *data = NULL;
-    err = socket_stream_data(io, &data);
-    if(!err){
-        data->flags = flags;
-    }
-    return err;
-}
-
-/** Write to the underlying socket using sendto.
- *
- * @param stream input
- * @param buf where to put input
- * @param n number of bytes to write
- * @return number of bytes written
- */
-static int socket_write(IOStream *s, const void *buf, size_t n){
-    SocketData *data = socket_data(s);
-    struct sockaddr *daddr = (struct sockaddr *)&data->daddr;
-    socklen_t daddr_n = sizeof(data->daddr);
-    int k;
-    dprintf("> sock=%d addr=%s:%d n=%d\n",
-            data->fd, inet_ntoa(data->daddr.sin_addr), ntohs(data->daddr.sin_port), n);
-    if(0){
-        struct sockaddr_in self = {};
-        socklen_t self_n;
-        getsockname(data->fd, (struct sockaddr *)&self, &self_n);
-        dprintf("> sockname sock=%d %s:%d\n",
-                data->fd, inet_ntoa(self.sin_addr), ntohs(self.sin_port));
-    }
-    k = sendto(data->fd, buf, n, data->flags, daddr, daddr_n);
-    dprintf("> sendto=%d\n", k);
-    return k;
-}
-
-/** Read from the underlying stream using recv();
- *
- * @param stream input
- * @param buf where to put input
- * @param n number of bytes to read
- * @return number of bytes read
- */
-static int socket_read(IOStream *s, void *buf, size_t n){
-    SocketData *data = socket_data(s);
-    int k;
-    struct sockaddr *saddr = (struct sockaddr *)&data->saddr;
-    socklen_t saddr_n = sizeof(data->saddr);
-    k = recvfrom(data->fd, buf, n, data->flags, saddr, &saddr_n);
-    return k;
-}
-
-/** Print to the underlying socket.
- *
- * @param s socket stream
- * @param msg format to use
- * @param args arguments
- * @return result of the print
- */
-static int socket_print(IOStream *s, const char *msg, va_list args){
-    SocketData *data = socket_data(s);
-    int n;
-    n = vsnprintf(data->buf, data->buf_n - 1, msg, args);
-    if(0 < n && n < data->buf_n){
-        socket_write(s, data->buf, n);
-    }
-    return n;
-}
-
-/** Read a character from the underlying socket
- *
- * @param s socket stream
- * @return character read, IOSTREAM_EOF on end of socket (or error)
- */
-static int socket_getc(IOStream *s){
-    char b;
-    int n, c;
-    n = socket_read(s, &b, 1);
-    c = (n <= 0 ? IOSTREAM_EOF : b);
-    return c;
-}
-
-/** Flush the socket (no-op).
- *
- * @param s socket stream
- * @return 0 on success, error code otherwise
- */
-static int socket_flush(IOStream *s){
-    return 0;
-}
-
-/** Check if a socket stream has an error (no-op).
- *
- * @param s socket stream
- * @return 1 if has an error, 0 otherwise
- */
-static int socket_error(IOStream *s){
-    // Read SOL_SOCKET/SO_ERROR ?
-    return 0;
-}
-
-/** Close a socket stream.
- *
- * @param s socket stream to close
- * @return result of the close
- */
-static int socket_close(IOStream *s){
-    SocketData *data = socket_data(s);
-    return close(data->fd);
-}
-
-/** Free a socket stream.
- *
- * @param s socket stream
- */
-static void socket_free(IOStream *s){
-    SocketData *data = socket_data(s);
-    deallocate(data);
-}
-
-/** Create an IOStream for a socket.
- *
- * @param fd socket to wtap
- * @return new IOStream using fd for i/o
- */
-IOStream *socket_stream_new(int fd){
-    int err = -ENOMEM;
-    IOStream *io = NULL;
-    SocketData *data = NULL;
-
-    io = ALLOCATE(IOStream);
-    if(!io) goto exit;
-    io->methods = &socket_methods;
-    data = ALLOCATE(SocketData);
-    if(!data) goto exit;
-    io->data = data;
-    data->fd = fd;
-    data->buf_n = sizeof(data->buf);
-    err = 0;
-  exit:
-    if(err){
-        if(io){
-            if(data) deallocate(data);
-            deallocate(io);
-            io = NULL;
-        }
-    }
-    return io;
-}
-
diff --git a/tools/lib/socket_stream.h b/tools/lib/socket_stream.h
deleted file mode 100644 (file)
index 5b8515f..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* $Id: socket_stream.h,v 1.2 2004/03/04 17:38:13 mjw Exp $ */
-/*
- * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _XEN_LIB_SOCKET_STREAM_H_
-#define _XEN_LIB_SOCKET_STREAM_H_
-
-#ifndef __KERNEL__
-#include "iostream.h"
-#include <stdio.h>
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-/** Data associated with a socket stream. */
-typedef struct SocketData {
-    /** The socket file descriptor. */
-    int fd;
-    /** Source address from last read (recvfrom). */
-    struct sockaddr_in saddr;
-    /** Destination address for writes (sendto). */
-    struct sockaddr_in daddr;
-    /** Write flags (sendto). */
-    int flags;
-    /** Buffer size. */
-    int buf_n;
-    /** Buffer for formatted printing. */
-    char buf[1024];
-} SocketData;
-
-extern IOStream *socket_stream_new(int fd);
-extern int socket_stream_data(IOStream *io, SocketData **data);
-extern int socket_stream_check(IOStream *io);
-extern int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr);
-extern int socket_stream_set_flags(IOStream *io, int flags);
-
-#endif
-#endif /* !_XEN_LIB_SOCKET_STREAM_H_ */
diff --git a/tools/lib/string_stream.c b/tools/lib/string_stream.c
deleted file mode 100644 (file)
index c3cf423..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Hewlett-Packard Company.
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/** @file
- * IOStream subtype for input and output to strings.
- * Usable from user or kernel code (with __KERNEL__ defined).
- */
-
-#include "sys_string.h"
-#include "string_stream.h"
-#include "allocate.h"
-
-static int string_print(IOStream *io, const char *msg, va_list args);
-static int string_getc(IOStream *io);
-static int string_error(IOStream *io);
-static int string_close(IOStream *io);
-static void string_free(IOStream *io);
-
-/** Methods for a string stream. */
-static IOMethods string_methods = {
-    //print: string_print,
-    //getc:  string_getc,
-    error: string_error,
-    close: string_close,
-    free:  string_free,
-};
-
-/** Get the string stream state.
- *
- * @param io string stream
- * @return state
- */
-static inline StringData *get_string_data(IOStream *io){
-    return (StringData*)io->data;
-}
-
-/** Read a character from a string stream.
- *
- * @param io string stream
- * @return character read, IOSTREAM_EOF if no more input
- */
-static int string_getc(IOStream *io){
-    StringData *data = get_string_data(io);
-    int c = IOSTREAM_EOF;
-    char *s = data->in;
-
-    if(s && s < data->end){
-        c = (unsigned)*s;
-        data->in = s+1;
-    }
-    return c;
-}
-
-/** Print to a string stream.
- * Formats the data to an internal buffer and prints it.
- * The formatted data must fit into the internal buffer.
- *
- * @param io string stream
- * @param format print format
- * @param args print arguments
- * @return result of the print
- */
-static int string_print(IOStream *io, const char *msg, va_list args){
-    StringData *data = get_string_data(io);
-    int k = data->end - data->out;
-    int n = vsnprintf(data->out, k, (char*)msg, args);
-    if(n < 0 || n > k ){
-        n = k;
-        IOStream_close(io);
-    } else {
-        data->out += n;
-    }
-    return n;
-}
-
-/** Test if a string stream has an error.
- *
- * @param io string stream
- * @return 0 if ok, error code otherwise
- */
-static int string_error(IOStream *io){
-    StringData *data = get_string_data(io);
-    return data->out == NULL;
-}
-
-/** Close a string stream.
- *
- * @param io string stream
- * @return 0
- */
-static int string_close(IOStream *io){
-    StringData *data = get_string_data(io);
-    data->in = NULL;
-    data->out = NULL;
-    return 0;
-}
-
-/** Free a string stream.
- * The stream must have been allocated, not statically created.
- * The stream state is freed, but the underlying string is not.
- *
- * @param io string stream
- */
-static void string_free(IOStream *io){
-    StringData *data = get_string_data(io);
-    zero(data, sizeof(*data));
-    deallocate(data);
-}
-
-/** Get the methods to use for a string stream.
- *
- * @return methods
- */
-IOMethods *string_stream_get_methods(void){
-    return &string_methods;
-}
-
-/** Initialise a string stream, usually from static data.
- *
- * @param io address of IOStream to fill in
- * @param data address of StringData to fill in
- * @param s string to use
- * @param n length of the string
- */
-void string_stream_init(IOStream *io, StringData *data, char *s, int n){
-    if(data && io){
-        zero(data, sizeof(*data));
-        data->string = (char*)s;
-        data->in = data->string;
-        data->out = data->string;
-        data->size = n;
-        data->end = data->string + n;
-        zero(io, sizeof(*io));
-        io->methods = &string_methods;
-        io->data = data;
-    }
-}
-
-/** Allocate and initialise a string stream.
- *
- * @param s string to use
- * @param n length of the string
- * @return new stream (free using IOStream_free)
- */
-IOStream *string_stream_new(char *s, int n){
-    int ok = 0;
-    StringData *data = ALLOCATE(StringData);
-    IOStream *io = ALLOCATE(IOStream);
-    if(data && io){
-        ok = 1;
-        string_stream_init(io, data, s, n);
-    }
-    if(!ok){
-        deallocate(data);
-        deallocate(io);
-        io = NULL;
-    }
-    return io;
-}
diff --git a/tools/lib/string_stream.h b/tools/lib/string_stream.h
deleted file mode 100644 (file)
index 36d764b..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* $Id: string_stream.h,v 1.1 2003/08/22 14:25:48 mjw Exp $ */
-/*
- * Copyright (C) 2001, 2002 Hewlett-Packard Company.
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _SP_STRING_STREAM_H_
-#define _SP_STRING_STREAM_H_
-
-#include "iostream.h"
-
-/** Internal state for a string stream.
- * Exposed here so that string streams can be statically created, using
- * string_stream_init().
- */
-typedef struct {
-    /** The string used for input and ouput. */
-    char *string;
-    /** Output pointer. */
-    char *out;
-    /** Input pointer. */
-    char *in;
-    /** Length of string. */
-    int size;
-    /** End marker. */
-    char *end;
-} StringData;
-
-extern IOMethods *string_stream_get_methods(void);
-extern IOStream *string_stream_new(char *s, int n);
-extern void string_stream_init(IOStream *stream, StringData *data, char *s, int n);
-
-#endif /* !_SP_STRING_STREAM_H_ */
diff --git a/tools/lib/sxpr.c b/tools/lib/sxpr.c
deleted file mode 100644 (file)
index adeffbe..0000000
+++ /dev/null
@@ -1,935 +0,0 @@
-/*
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or  (at your option) any later version. This library is 
- * distributed in the  hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#include <stdarg.h>
-#include "sys_string.h"
-#include "lexis.h"
-#include "sys_net.h"
-#include "hash_table.h"
-#include "sxpr.h"
-
-#include <errno.h>
-#undef free
-
-/** @file
- * General representation of sxprs.
- * Includes print, equal, and free functions for the sxpr types.
- *
- * Zero memory containing an Sxpr will have the value ONONE - this is intentional.
- * When a function returning an sxpr cannot allocate memory we return ONOMEM.
- *
- */
-
-static int atom_print(IOStream *io, Sxpr obj, unsigned flags);
-static int atom_equal(Sxpr x, Sxpr y);
-static void atom_free(Sxpr obj);
-
-static int string_print(IOStream *io, Sxpr obj, unsigned flags);
-static int string_equal(Sxpr x, Sxpr y);
-static void string_free(Sxpr obj);
-
-static int cons_print(IOStream *io, Sxpr obj, unsigned flags);
-static int cons_equal(Sxpr x, Sxpr y);
-static void cons_free(Sxpr obj);
-
-static int null_print(IOStream *io, Sxpr obj, unsigned flags);
-static int none_print(IOStream *io, Sxpr obj, unsigned flags);
-static int int_print(IOStream *io, Sxpr obj, unsigned flags);
-static int bool_print(IOStream *io, Sxpr obj, unsigned flags);
-
-/** Type definitions. */
-static SxprType types[1024] = {
-    [T_NONE]     { type:    T_NONE,     name: "none",       print: none_print      },
-    [T_NULL]     { type:    T_NULL,     name: "null",       print: null_print      },
-    [T_UINT]     { type:    T_UINT,     name: "int",        print: int_print,      },
-    [T_BOOL]     { type:    T_BOOL,     name: "bool",       print: bool_print,     },
-    [T_ATOM]     { type:    T_ATOM,     name: "atom",       print: atom_print,
-                  pointer: TRUE,
-                  free:    atom_free,
-                  equal:   atom_equal,
-                },
-    [T_STRING]   { type:    T_STRING,   name: "string",     print: string_print,
-                  pointer: TRUE,
-                  free:    string_free,
-                  equal:   string_equal,
-                },
-    [T_CONS]     { type:    T_CONS,     name: "cons",       print: cons_print,
-                  pointer: TRUE,
-                  free:    cons_free,
-                  equal:   cons_equal,
-                },
-};
-
-/** Number of entries in the types array. */
-static int type_sup = sizeof(types)/sizeof(types[0]);
-
-/** Get the type definition for a given type code.
- *
- * @param ty type code
- * @return type definition or null
- */
-SxprType *get_sxpr_type(int ty){
-    if(0 <= ty && ty < type_sup){
-        return types+ty;
-    }
-    return NULL;
-}
-
-/** The default print function.
- *
- * @param io stream to print to
- * @param x sxpr to print
- * @param flags print flags
- * @return number of bytes written on success
- */
-int default_print(IOStream *io, Sxpr x, unsigned flags){
-    return IOStream_print(io, "#<%u %lu>\n", get_type(x), get_ul(x));
-}
-
-/** The default equal function.
- * Uses eq().
- *
- * @param x sxpr to compare
- * @param y sxpr to compare
- * @return 1 if equal, 0 otherwise
- */
-int default_equal(Sxpr x, Sxpr y){
-    return eq(x, y);
-}
-
-/** General sxpr print function.
- * Prints an sxpr on a stream using the print function for the sxpr type.
- * Printing is controlled by flags from the PrintFlags enum.
- * If PRINT_TYPE is in the flags the sxpr type is printed before the sxpr
- * (for debugging).
- *
- * @param io stream to print to
- * @param x sxpr to print
- * @param flags print flags
- * @return number of bytes written
- */
-int objprint(IOStream *io, Sxpr x, unsigned flags){
-    SxprType *def = get_sxpr_type(get_type(x));
-    ObjPrintFn *print_fn = (def && def->print ? def->print : default_print);
-    int k = 0;
-    if(!io) return k;
-    if(flags & PRINT_TYPE){
-       k += IOStream_print(io, "%s:", def->name);
-    }
-    k += print_fn(io, x, flags);
-    return k;
-}
-
-/** General sxpr free function.
- * Frees an sxpr using the free function for its type.
- * Free functions must recursively free any subsxprs.
- * If no function is defined then the default is to
- * free sxprs whose type has pointer true.
- * Sxprs must not be used after freeing.
- *
- * @param x sxpr to free
- */
-void objfree(Sxpr x){
-    SxprType *def = get_sxpr_type(get_type(x));
-
-    if(def){
-       if(def->free){
-           def->free(x);
-       } else if (def->pointer){
-           hfree(x);
-       }
-    }
-}
-
-/** General sxpr equality function.
- * Compares x and y using the equal function for x.
- * Uses default_equal() if x has no equal function.
- *
- * @param x sxpr to compare
- * @param y sxpr to compare
- * @return 1 if equal, 0 otherwise
- */
-int objequal(Sxpr x, Sxpr y){
-    SxprType *def = get_sxpr_type(get_type(x));
-    ObjEqualFn *equal_fn = (def && def->equal ? def->equal : default_equal);
-    return equal_fn(x, y);
-}
-
-/** Search for a key in an alist.
- * An alist is a list of conses, where the cars
- * of the conses are the keys. Compares keys using equality.
- *
- * @param k key
- * @param l alist to search
- * @return first element of l with car k, or ONULL
- */
-Sxpr assoc(Sxpr k, Sxpr l){
-    for( ; CONSP(l) ; l = CDR(l)){
-        Sxpr x = CAR(l);
-        if(CONSP(x) && objequal(k, CAR(x))){
-            return x;   
-        }
-    }
-    return ONULL;
-}
-
-/** Search for a key in an alist.
- * An alist is a list of conses, where the cars
- * of the conses are the keys. Compares keys using eq.
- *
- * @param k key
- * @param l alist to search
- * @return first element of l with car k, or ONULL
- */
-Sxpr assocq(Sxpr k, Sxpr l){
-    for( ; CONSP(l); l = CDR(l)){
-        Sxpr x = CAR(l);
-        if(CONSP(x) && eq(k, CAR(x))){
-            return x;
-        }
-    }
-    return ONULL;
-}
-
-/** Add a new key and value to an alist.
- *
- * @param k key
- * @param l value
- * @param l alist
- * @return l with the new cell added to the front
- */
-Sxpr acons(Sxpr k, Sxpr v, Sxpr l){
-    Sxpr x, y;
-    x = cons_new(k, v);
-    if(NOMEMP(x)) return x;
-    y = cons_new(x, l);
-    if(NOMEMP(y)) cons_free_cells(x);
-    return y;
-}
-
-/** Test if a list contains an element.
- * Uses sxpr equality.
- *
- * @param l list
- * @param x element to look for
- * @return a tail of l with x as car, or ONULL
- */
-Sxpr cons_member(Sxpr l, Sxpr x){
-    for( ; CONSP(l) && !eq(x, CAR(l)); l = CDR(l)){}
-    return l;
-}
-
-/** Test if a list contains an element satisfying a test.
- * The test function is called with v and an element of the list.
- *
- * @param l list
- * @param test_fn test function to use
- * @param v value for first argument to the test
- * @return a tail of l with car satisfying the test, or 0
- */
-Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
-    for( ; CONSP(l) && !test_fn(v, CAR(l)); l = CDR(l)){ }
-    return l;
-}
-
-/** Test if the elements of list 't' are a subset of the elements
- * of list 's'. Element order is not significant.
- *
- * @param s element list to check subset of
- * @param t element list to check if is a subset
- * @return 1 if is a subset, 0 otherwise
- */
-int cons_subset(Sxpr s, Sxpr t){
-    for( ; CONSP(t); t = CDR(t)){
-       if(!CONSP(cons_member(s, CAR(t)))){
-           return 0;
-       }
-    }
-    return 1;
-}
-
-/** Test if two lists have equal sets of elements.
- * Element order is not significant.
- *
- * @param s list to check
- * @param t list to check
- * @return 1 if equal, 0 otherwise
- */
-int cons_set_equal(Sxpr s, Sxpr t){
-    return cons_subset(s, t) && cons_subset(t, s);
-}
-
-#ifdef USE_GC
-/*============================================================================*/
-/* The functions inside this ifdef are only safe if GC is used.
- * Otherwise they may leak memory.
- */
-
-/** Remove an element from a list (GC only).
- * Uses sxpr equality and removes all instances, even
- * if there are more than one.
- *
- * @param l list to remove elements from
- * @param x element to remove
- * @return modified input list
- */
-Sxpr cons_remove(Sxpr l, Sxpr x){
-    return cons_remove_if(l, eq, x);
-}
-
-/** Remove elements satisfying a test (GC only).
- * The test function is called with v and an element of the set.
- *
- * @param l list to remove elements from
- * @param test_fn function to use to decide if an element should be removed
- * @return modified input list
- */
-Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
-    Sxpr prev = ONULL, elt, next;
-
-    for(elt = l; CONSP(elt); elt = next){
-        next = CDR(elt);
-        if(test_fn(v, CAR(elt))){
-            if(NULLP(prev)){
-                l = next;
-            } else {
-                CDR(prev) = next;
-            }
-        }
-    }
-    return l;
-}
-
-/** Set the value for a key in an alist (GC only).
- * If the key is present, changes the value, otherwise
- * adds a new cell.
- *
- * @param k key
- * @param v value
- * @param l alist
- * @return modified or extended list
- */
-Sxpr setf(Sxpr k, Sxpr v, Sxpr l){
-    Sxpr e = assoc(k, l);
-    if(NULLP(e)){
-        l = acons(k, v, l);
-    } else {
-        CAR(CDR(e)) = v;
-    }
-    return l;
-}
-/*============================================================================*/
-#endif /* USE_GC */
-
-/** Create a new atom with the given name.
- *
- * @param name the name
- * @return new atom
- */
-Sxpr atom_new(char *name){
-    Sxpr n, obj = ONOMEM;
-
-    n = string_new(name);
-    if(NOMEMP(n)) goto exit;
-    obj = HALLOC(ObjAtom, T_ATOM);
-    if(NOMEMP(obj)) goto exit;
-    OBJ_ATOM(obj)->name = n;
-  exit:
-    return obj;
-}
-
-/** Free an atom.
- *
- * @param obj to free
- */
-void atom_free(Sxpr obj){
-    // Interned atoms are shared, so do not free.
-    if(OBJ_ATOM(obj)->interned) return;
-    objfree(OBJ_ATOM(obj)->name);
-    hfree(obj);
-}
-
-/** Print an atom. Prints the atom name.
- *
- * @param io stream to print to
- * @param obj to print
- * @param flags print flags
- * @return number of bytes printed
- */
-int atom_print(IOStream *io, Sxpr obj, unsigned flags){
-    //return string_print(io, OBJ_ATOM(obj)->name, (flags | PRINT_RAW));
-    return string_print(io, OBJ_ATOM(obj)->name, flags);
-}
-
-/** Atom equality.
- *
- * @param x to compare
- * @param y to compare
- * @return 1 if equal, 0 otherwise
- */
-int atom_equal(Sxpr x, Sxpr y){
-    int ok;
-    ok = eq(x, y);
-    if(ok) goto exit;
-    ok = ATOMP(y) && string_equal(OBJ_ATOM(x)->name, OBJ_ATOM(y)->name);
-    if(ok) goto exit;
-    ok = STRINGP(y) && string_equal(OBJ_ATOM(x)->name, y);
-  exit:
-    return ok;
-}
-
-/** Get the name of an atom.
- *
- * @param obj atom
- * @return name
- */
-char * atom_name(Sxpr obj){
-    return string_string(OBJ_ATOM(obj)->name);
-}
-
-/** Get the C string from a string sxpr.
- *
- * @param obj string sxpr
- * @return string
- */
-char * string_string(Sxpr obj){
-    return OBJ_STRING(obj);
-}
-
-/** Get the length of a string.
- *
- * @param obj string
- * @return length
- */
-int string_length(Sxpr obj){
-    return strlen(OBJ_STRING(obj));
-}
-
-/** Create a new string. The input string is copied,
- * and must be null-terminated.
- *
- * @param s characters to put in the string
- * @return new sxpr
- */
-Sxpr string_new(char *s){
-    int n = (s ? strlen(s) : 0);
-    Sxpr obj;
-    obj = halloc(n+1, T_STRING);
-    if(!NOMEMP(obj)){
-        char *str = OBJ_STRING(obj);
-        strncpy(str, s, n);
-        str[n] = '\0';
-    }
-    return obj;
-}
-
-/** Free a string.
- *
- * @param obj to free
- */
-void string_free(Sxpr obj){
-    hfree(obj);
-}
-
-/** Determine if a string needs escapes when printed
- * using the given flags.
- *
- * @param str string to check
- * @param flags print flags
- * @return 1 if needs escapes, 0 otherwise
- */
-int needs_escapes(char *str, unsigned flags){
-    char *c;
-    int val = 0;
-
-    if(str){
-       for(c=str; *c; c++){
-           if(in_alpha_class(*c)) continue;
-           if(in_decimal_digit_class(*c)) continue;
-           if(in_class(*c, "/._+:@~-")) continue;
-           val = 1;
-           break;
-       }
-    }
-    //printf("\n> val=%d str=|%s|\n", val, str);
-    return val;
-}
-
-/** Print a string to a stream, with escapes if necessary.
- *
- * @param io stream to print to
- * @param str string
- * @param flags print flags
- * @return number of bytes written
- */
-int _string_print(IOStream *io, char *str, unsigned flags){
-    int k = 0;
-    if((flags & PRINT_RAW) || !needs_escapes(str, flags)){
-        k += IOStream_print(io, str);
-    } else {
-       k += IOStream_print(io, "\"");
-       if(str){
-            char *s;
-            for(s = str; *s; s++){
-                if(*s < ' ' || *s >= 127 ){
-                    switch(*s){
-                    case '\a': k += IOStream_print(io, "\\a");  break;
-                    case '\b': k += IOStream_print(io, "\\b");  break;
-                    case '\f': k += IOStream_print(io, "\\f");  break;
-                    case '\n': k += IOStream_print(io, "\\n");  break;
-                    case '\r': k += IOStream_print(io, "\\r");  break;
-                    case '\t': k += IOStream_print(io, "\\t");  break;
-                    case '\v': k += IOStream_print(io, "\\v");  break;
-                    default:
-                        // Octal escape;
-                        k += IOStream_print(io, "\\%o", *s);
-                        break;
-                    }
-                } else if(*s == c_double_quote ||
-                          *s == c_single_quote ||
-                          *s == c_escape){
-                    k += IOStream_print(io, "\\%c", *s);
-                } else {
-                    k+= IOStream_print(io, "%c", *s);
-                }
-            }
-       }
-       k += IOStream_print(io, "\"");
-    }
-    return k;
-}
-
-/** Print a string to a stream, with escapes if necessary.
- *
- * @param io stream to print to
- * @param obj string
- * @param flags print flags
- * @return number of bytes written
- */
-int string_print(IOStream *io, Sxpr obj, unsigned flags){
-    return _string_print(io, OBJ_STRING(obj), flags);
-}
-
-/** Compare an sxpr with a string for equality.
- *
- * @param x string to compare with
- * @param y sxpr to compare
- * @return 1 if equal, 0 otherwise
- */
-int string_equal(Sxpr x, Sxpr y){
-    int ok = 0;
-    ok = eq(x,y);
-    if(ok) goto exit;
-    ok = has_type(y, T_STRING) && !strcmp(OBJ_STRING(x), OBJ_STRING(y));
-    if(ok) goto exit;
-    ok = has_type(y, T_ATOM) && !strcmp(OBJ_STRING(x), atom_name(y));
-  exit:
-    return ok;
-}
-
-/** Create a new cons cell.
- * The cell is ONOMEM if either argument is.
- *
- * @param car sxpr for the car
- * @param cdr sxpr for the cdr
- * @return new cons
- */
-Sxpr cons_new(Sxpr car, Sxpr cdr){
-    Sxpr obj;
-    if(NOMEMP(car) || NOMEMP(cdr)){
-        obj = ONOMEM;
-    } else {
-        obj = HALLOC(ObjCons, T_CONS);
-        if(!NOMEMP(obj)){
-            ObjCons *z = OBJ_CONS(obj);
-            z->car = car;
-            z->cdr = cdr;
-        }
-    }
-    return obj;
-}
-
-/** Push a new element onto a list.
- *
- * @param list list to add to
- * @param elt element to add
- * @return 0 if successful, error code otherwise
- */
-int cons_push(Sxpr *list, Sxpr elt){
-    Sxpr l;
-    l = cons_new(elt, *list);
-    if(NOMEMP(l)) return -ENOMEM;
-    *list = l;
-    return 0;
-}
-
-/** Free a cons. Recursively frees the car and cdr.
- *
- * @param obj to free
- */
-void cons_free(Sxpr obj){
-    Sxpr next;
-    for(; CONSP(obj); obj = next){
-       next = CDR(obj);
-       objfree(CAR(obj));
-       hfree(obj);
-    }
-    if(!NULLP(obj)){
-       objfree(obj);
-    }
-}
-
-/** Free a cons and its cdr cells, but not the car sxprs.
- * Does nothing if called on something that is not a cons.
- *
- * @param obj to free
- */
-void cons_free_cells(Sxpr obj){
-    Sxpr next;
-    for(; CONSP(obj); obj = next){
-       next = CDR(obj);
-       hfree(obj);
-    }
-}
-
-/** Print a cons.
- * Prints the cons in list format if the cdrs are conses.
- * uses pair (dot) format if the last cdr is not a cons (or null).
- *
- * @param io stream to print to
- * @param obj to print
- * @param flags print flags
- * @return number of bytes written
- */
-int cons_print(IOStream *io, Sxpr obj, unsigned flags){
-    int first = 1;
-    int k = 0;
-    k += IOStream_print(io, "(");
-    for( ; CONSP(obj) ; obj = CDR(obj)){
-        if(first){ 
-            first = 0;
-        } else {
-            k += IOStream_print(io, " ");
-        }
-        k += objprint(io, CAR(obj), flags);
-    }
-    if(!NULLP(obj)){
-        k += IOStream_print(io, " . ");
-        k += objprint(io, obj, flags);
-    }
-    k += IOStream_print(io, ")");
-    return (IOStream_error(io) ? -1 : k);
-}
-
-/** Compare a cons with another sxpr for equality.
- * If y is a cons, compares the cars and cdrs recursively.
- *
- * @param x cons to compare
- * @param y sxpr to compare
- * @return 1 if equal, 0 otherwise
- */
-int cons_equal(Sxpr x, Sxpr y){
-    return CONSP(y) &&
-        objequal(CAR(x), CAR(y)) &&
-        objequal(CDR(x), CDR(y));
-}
-
-/** Return the length of a cons list.
- *
- * @param obj list
- * @return length
- */
-int cons_length(Sxpr obj){
-    int count = 0;
-    for( ; CONSP(obj); obj = CDR(obj)){
-        count++;
-    }
-    return count;
-}
-
-/** Destructively reverse a cons list in-place.
- * If the argument is not a cons it is returned unchanged.
- * 
- * @param l to reverse
- * @return reversed list
- */
-Sxpr nrev(Sxpr l){
-    if(CONSP(l)){
-       // Iterate down the cells in the list making the cdr of
-       // each cell point to the previous cell. The last cell 
-       // is the head of the reversed list.
-       Sxpr prev = ONULL;
-       Sxpr cell = l;
-       Sxpr next;
-
-       while(1){
-           next = CDR(cell);
-           CDR(cell) = prev;
-           if(!CONSP(next)) break;
-           prev = cell;
-           cell = next;
-       }
-       l = cell;
-    }
-    return l;
-}
-
-/** Print the null sxpr.       
- *
- * @param io stream to print to
- * @param obj to print
- * @param flags print flags
- * @return number of bytes written
- */
-static int null_print(IOStream *io, Sxpr obj, unsigned flags){
-    return IOStream_print(io, "()");
-}
-
-/** Print the `unspecified' sxpr none.
- *
- * @param io stream to print to
- * @param obj to print
- * @param flags print flags
- * @return number of bytes written
- */
-static int none_print(IOStream *io, Sxpr obj, unsigned flags){
-    return IOStream_print(io, "<none>");
-}
-
-/** Print an integer.
- *
- * @param io stream to print to
- * @param obj to print
- * @param flags print flags
- * @return number of bytes written
- */
-static int int_print(IOStream *io, Sxpr obj, unsigned flags){
-    return IOStream_print(io, "%d", OBJ_INT(obj));
-}
-
-/** Print a boolean.
- *
- * @param io stream to print to
- * @param obj to print
- * @param flags print flags
- * @return number of bytes written
- */
-static int bool_print(IOStream *io, Sxpr obj, unsigned flags){
-    return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false));
-}
-
-int sxprp(Sxpr obj, Sxpr name){
-    return CONSP(obj) && objequal(CAR(obj), name);
-}
-
-/** Get the name of an element.
- * 
- * @param obj element
- * @return name
- */
-Sxpr sxpr_name(Sxpr obj){
-    Sxpr val = ONONE;
-    if(CONSP(obj)){
-        val = CAR(obj);
-    } else if(STRINGP(obj) || ATOMP(obj)){
-        val = obj;
-    }
-    return val;
-}
-
-int sxpr_is(Sxpr obj, char *s){
-    if(ATOMP(obj)) return !strcmp(atom_name(obj), s);
-    if(STRINGP(obj)) return !strcmp(string_string(obj), s);
-    return 0;
-}
-
-int sxpr_elementp(Sxpr obj, Sxpr name){
-    return CONSP(obj) && objequal(CAR(obj), name);
-}
-
-/** Get the attributes of an sxpr.
- * 
- * @param obj sxpr
- * @return attributes
- */
-Sxpr sxpr_attributes(Sxpr obj){
-    Sxpr val = ONULL;
-    if(CONSP(obj)){
-        obj = CDR(obj);
-        if(CONSP(obj)){
-            obj = CAR(obj);
-            if(sxprp(obj, intern("@"))){
-                val = CDR(obj);
-            }
-        }
-    }
-    return val;
-}
-
-Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def){
-    Sxpr val = ONONE;
-    val = assoc(sxpr_attributes(obj), key);
-    if(CONSP(val) && CONSP(CDR(val))){
-        val = CADR(def);
-    } else {
-        val = def;
-    }
-    return val;
-}
-
-/** Get the children of an sxpr.
- * 
- * @param obj sxpr
- * @return children
- */
-Sxpr sxpr_children(Sxpr obj){
-    Sxpr val = ONULL;
-    if(CONSP(obj)){
-        val = CDR(obj);
-        if(CONSP(val) && sxprp(CAR(val), intern("@"))){
-            val = CDR(val);
-        }
-    }
-    return val;
-}
-
-Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def){
-    Sxpr val = ONONE;
-    Sxpr l;
-    for(l = sxpr_children(obj); CONSP(l); l = CDR(l)){
-        if(sxprp(CAR(l), name)){
-            val = CAR(l);
-            break;
-        }
-    }
-    if(NONEP(val)) val = def;
-    return val;
-}
-
-Sxpr sxpr_child0(Sxpr obj, Sxpr def){
-    Sxpr val = ONONE;
-    Sxpr l = sxpr_children(obj);
-    if(CONSP(l)){
-        val = CAR(l);
-    } else {
-        val = def;
-    }
-    return val;
-}
-
-Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def){
-    Sxpr val = ONONE;
-    val = sxpr_child(obj, name, ONONE);
-    if(NONEP(val)){
-        val = def;
-    } else {
-        val = sxpr_child0(val, def);
-    }
-    return val;
-}
-
-/** Table of interned symbols. Indexed by symbol name. */
-static HashTable *symbols = NULL;
-
-/** Hash function for entries in the symbol table.
- *
- * @param key to hash
- * @return hashcode
- */
-static Hashcode sym_hash_fn(void *key){
-    return hash_string((char*)key);
-}
-
-/** Key equality function for the symbol table.
- *
- * @param x to compare
- * @param y to compare
- * @return 1 if equal, 0 otherwise
- */
-static int sym_equal_fn(void *x, void *y){
-    return !strcmp((char*)x, (char*)y);
-}
-
-/** Entry free function for the symbol table.
- *
- * @param table the entry is in
- * @param entry being freed
- */
-static void sym_free_fn(HashTable *table, HTEntry *entry){
-    if(entry){
-       objfree(((ObjAtom*)entry->value)->name);
-       HTEntry_free(entry);
-    }
-}
-       
-/** Initialize the symbol table.
- *
- * @return 0 on sucess, error code otherwise
- */
-static int init_symbols(void){
-    symbols = HashTable_new(100);
-    if(symbols){
-        symbols->key_hash_fn = sym_hash_fn;
-        symbols->key_equal_fn = sym_equal_fn;
-       symbols->entry_free_fn = sym_free_fn;
-        return 0;
-    }
-    return -1;
-}
-
-/** Cleanup the symbol table. Frees the table and all its symbols.
- */
-void cleanup_symbols(void){
-    HashTable_free(symbols);
-    symbols = NULL;
-}
-
-/** Get the interned symbol with the given name.
- * No new symbol is created.
- *
- * @return symbol or null
- */
-Sxpr get_symbol(char *sym){
-    HTEntry *entry;
-    if(!symbols){
-       if(init_symbols()) return ONOMEM;
-       return ONULL;
-    }
-    entry = HashTable_get_entry(symbols, sym);
-    if(entry){
-        return OBJP(T_ATOM, entry->value);
-    } else {
-        return ONULL;
-    }
-}
-
-/** Get the interned symbol with the given name.
- * Creates a new symbol if necessary.
- *
- * @return symbol
- */
-Sxpr intern(char *sym){
-    Sxpr symbol = get_symbol(sym);
-    if(NULLP(symbol)){
-       if(!symbols) return ONOMEM;
-        symbol = atom_new(sym);
-        if(!NOMEMP(symbol)){
-           OBJ_ATOM(symbol)->interned = TRUE;
-            HashTable_add(symbols, atom_name(symbol), get_ptr(symbol));
-        }
-    }
-    return symbol;
-}
diff --git a/tools/lib/sxpr.h b/tools/lib/sxpr.h
deleted file mode 100644 (file)
index b900831..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or  (at your option) any later version. This library is 
- * distributed in the  hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-#ifndef _XEN_LIB_SXPR_H_
-#define _XEN_LIB_SXPR_H_
-
-#include <stdint.h>
-
-#include "hash_table.h"
-#include "iostream.h"
-#include "allocate.h"
-
-/** @file
- * Definitions for rules and sxprs.
- */
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-/** Sxpr type. */
-typedef int16_t TypeCode;
-
-/** A typed sxpr handle.*/
-typedef struct Sxpr {
-    /** Sxpr type. */
-    TypeCode type;
-    union {
-       /** Sxpr value. */
-        unsigned long ul;
-       /** Pointer. */
-        void *ptr;
-    } v;
-} Sxpr;
-
-/** Sxpr type to indicate out of memory. */
-#define T_NOMEM      ((TypeCode)-1)
-/** The 'unspecified' sxpr. */
-#define T_NONE       ((TypeCode)0)
-/** The empty list. */
-#define T_NULL       ((TypeCode)1)
-/** Unsigned integer. */
-#define T_UINT       ((TypeCode)2)
-/** A string. */
-#define T_STRING     ((TypeCode)3)
-/** An atom. */
-#define T_ATOM       ((TypeCode)4)
-/** A boolean. */
-#define T_BOOL       ((TypeCode)5)
-
-/** A cons (pair or list). */
-#define T_CONS       ((TypeCode)10)
-
-/** An error. */
-#define T_ERR        ((TypeCode)40)
-
-/** An atom. */
-typedef struct ObjAtom {
-    Sxpr name;
-    Hashcode hashcode;
-    int interned;
-} ObjAtom;
-
-/** A cons (pair). */
-typedef struct ObjCons {
-    Sxpr car;
-    Sxpr cdr;
-} ObjCons;
-
-/** A vector. */
-typedef struct ObjVector {
-    int n;
-    Sxpr data[0];
-} ObjVector;
-
-/** Flags for sxpr printing. */
-enum PrintFlags {
-    PRINT_RAW           = 0x001,
-    PRINT_TYPE          = 0x002,
-    PRINT_PRETTY        = 0x004,
-    PRINT_NUM           = 0x008,
-};
-
-/** An integer sxpr.
- *
- * @param ty type
- * @param val integer value
- */
-#define OBJI(ty, val) (Sxpr){ type: (ty), v: { ul: (val) }}
-
-/** A pointer sxpr.
- * If the pointer is non-null, returns an sxpr containing it.
- * If the pointer is null, returns ONOMEM.
- *
- * @param ty type
- * @param val pointer
- */
-#define OBJP(ty, val) ((val) ? (Sxpr){ type: (ty), v: { ptr: (val) }} : ONOMEM)
-
-/** Make an integer sxpr containing a pointer.
- *
- * @param val pointer
- */
-#define PTR(val) OBJP(T_UINT, (void*)(val))
-
-/** Make an integer sxpr.
- * @param x value
- */
-#define OINT(x)       OBJI(T_UINT,  x)
-
-/** Make an error sxpr.
- *
- * @param x value
- */
-#define OERR(x)       OBJI(T_ERR,   x)
-
-/** Out of memory constant. */
-#define ONOMEM        OBJI(T_NOMEM, 0)
-
-/** The `unspecified' constant. */
-#define ONONE         OBJI(T_NONE,  0)
-
-/** Empty list constant. */
-#define ONULL         OBJI(T_NULL,  0)
-
-/** False constant. */
-#define OFALSE        OBJI(T_BOOL,  0)
-
-/** True constant. */
-#define OTRUE         OBJI(T_BOOL,  1)
-
-/* Recognizers for the various sxpr types.  */
-#define ATOMP(obj)        has_type(obj, T_ATOM)
-#define BOOLP(obj)        has_type(obj, T_BOOL)
-#define CONSP(obj)        has_type(obj, T_CONS)
-#define ERRP(obj)         has_type(obj, T_ERR)
-#define INTP(obj)         has_type(obj, T_UINT)
-#define NOMEMP(obj)       has_type(obj, T_NOMEM)
-#define NONEP(obj)        has_type(obj, T_NONE)
-#define NULLP(obj)        has_type(obj, T_NULL)
-#define STRINGP(obj)      has_type(obj, T_STRING)
-
-#define TRUEP(obj)    get_ul(obj)
-
-/** Convert an sxpr to an unsigned integer. */
-#define OBJ_UINT(x)   get_ul(x)
-/** Convert an sxpr to an integer. */
-#define OBJ_INT(x)    (int)get_ul(x)
-
-/* Conversions of sxprs to their values.
- * No checking is done.
- */
-#define OBJ_STRING(x)  ((char*)get_ptr(x))
-#define OBJ_CONS(x)    ((ObjCons*)get_ptr(x))
-#define OBJ_ATOM(x)    ((ObjAtom*)get_ptr(x))
-#define OBJ_SET(x)     ((ObjSet*)get_ptr(x))
-#define CAR(x)         (OBJ_CONS(x)->car)
-#define CDR(x)         (OBJ_CONS(x)->cdr)
-
-#define CAAR(x)        (CAR(CAR(x)))
-#define CADR(x)        (CAR(CDR(x)))
-#define CDAR(x)        (CDR(CAR(x)))
-#define CDDR(x)        (CDR(CDR(x)))
-
-/** Get the integer value from an sxpr.
- *
- * @param obj sxpr
- * @return value
- */
-static inline unsigned long get_ul(Sxpr obj){
-    return obj.v.ul;
-}
-
-/** Get the pointer value from an sxpr.
- *
- * @param obj sxpr
- * @return value
- */
-static inline void * get_ptr(Sxpr obj){
-    return obj.v.ptr;
-}
-
-/** Create an sxpr containing a pointer.
- *
- * @param type typecode
- * @param val pointer
- * @return sxpr
- */
-static inline Sxpr obj_ptr(TypeCode type, void *val){
-    return (Sxpr){ type: type, v: { ptr: val } };
-}
-
-/** Create an sxpr containing an integer.
- *
- * @param type typecode
- * @param val integer
- * @return sxpr
- */
-static inline Sxpr obj_ul(TypeCode type, unsigned long val){
-    return (Sxpr){ type: type, v: { ul: val } };
-}
-
-/** Get the type of an sxpr.
- *
- * @param obj sxpr
- * @return type
- */
-static inline TypeCode get_type(Sxpr obj){
-    return obj.type;
-}
-
-/** Check the type of an sxpr.
- *
- * @param obj sxpr
- * @param type to check
- * @return 1 if has the type, 0 otherwise
- */
-static inline int has_type(Sxpr obj, TypeCode type){
-    return get_type(obj) == type;
-}
-
-/** Compare sxprs for literal equality of type and value.
- *
- * @param x sxpr to compare
- * @param y sxpr to compare
- * @return 1 if equal, 0 otherwise
- */
-static inline int eq(Sxpr x, Sxpr y){
-    return ((get_type(x) == get_type(y)) && (get_ul(x) == get_ul(y)));
-}
-
-/** Checked version of CAR
- *
- * @param x sxpr
- * @return CAR if a cons, x otherwise
- */
-static inline Sxpr car(Sxpr x){
-    return (CONSP(x) ? CAR(x) : x);
-}
-
-/** Checked version of CDR.
- *
- * @param x sxpr
- * @return CDR if a cons, null otherwise
- */
-static inline Sxpr cdr(Sxpr x){
-    return (CONSP(x) ? CDR(x) : ONULL);
-}
-
-/** Allocate some memory and return an sxpr containing it.
- * Returns ONOMEM if allocation failed.
- *
- * @param n number of bytes to allocate
- * @param ty typecode
- * @return sxpr
- */
-static inline Sxpr halloc(size_t n,  TypeCode ty){
-    return OBJP(ty, allocate(n));
-}
-
-/** Allocate an sxpr containing a pointer to the given type.
- *
- * @param ty type (uses sizeof to determine how many bytes to allocate)
- * @param code typecode
- * @return sxpr, ONOMEM if allocation failed
- */
-#define HALLOC(ty, code) halloc(sizeof(ty), code)
-
-typedef int ObjPrintFn(IOStream *io, Sxpr obj, unsigned flags);
-typedef int ObjEqualFn(Sxpr obj, Sxpr other);
-typedef void ObjFreeFn(Sxpr obj);
-
-/** An sxpr type definition. */
-typedef struct SxprType {
-    TypeCode type;
-    char *name;
-    int pointer;
-    ObjPrintFn *print;
-    ObjEqualFn *equal;
-    ObjFreeFn *free;
-} SxprType;
-
-
-extern SxprType *get_sxpr_type(int ty);
-
-/** Free the pointer in an sxpr.
- *
- * @param x sxpr containing a pointer
- */
-static inline void hfree(Sxpr x){
-    deallocate(get_ptr(x));
-}
-
-extern int objprint(IOStream *io, Sxpr x, unsigned flags);
-extern int objequal(Sxpr x, Sxpr y);
-extern void objfree(Sxpr x);
-
-extern void cons_free_cells(Sxpr obj);
-extern Sxpr intern(char *s);
-
-extern Sxpr assoc(Sxpr k, Sxpr l);
-extern Sxpr assocq(Sxpr k, Sxpr l);
-extern Sxpr acons(Sxpr k, Sxpr v, Sxpr l);
-extern Sxpr nrev(Sxpr l);
-extern Sxpr cons_member(Sxpr l, Sxpr x);
-extern Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
-extern int cons_subset(Sxpr s, Sxpr t);
-extern int cons_set_equal(Sxpr s, Sxpr t);
-
-#ifdef USE_GC
-extern Sxpr cons_remove(Sxpr l, Sxpr x);
-extern Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
-#endif
-
-extern Sxpr atom_new(char *name);
-extern char * atom_name(Sxpr obj);
-
-extern Sxpr string_new(char *s);
-extern char * string_string(Sxpr obj);
-extern int string_length(Sxpr obj);
-
-extern Sxpr cons_new(Sxpr car, Sxpr cdr);
-extern int cons_push(Sxpr *list, Sxpr elt);
-extern int cons_length(Sxpr obj);
-
-Sxpr sxpr_name(Sxpr obj);
-int sxpr_is(Sxpr obj, char *s);
-int sxpr_elementp(Sxpr obj, Sxpr name);
-Sxpr sxpr_attributes(Sxpr obj);
-Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def);
-Sxpr sxpr_children(Sxpr obj);
-Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def);
-Sxpr sxpr_child0(Sxpr obj, Sxpr def);
-Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def);
-
-/** Create a new atom.
- *
- * @param s atom name
- * @return new atom
- */
-static inline Sxpr mkatom(char *s){
-    return atom_new(s);
-}
-
-/** Create a new string sxpr.
- *
- * @param s string bytes (copied)
- * @return new string
- */
-static inline Sxpr mkstring(char *s){
-    return string_new(s);
-}
-
-/** Create an integer sxpr.
- *
- * @param i value
- * @return sxpr
- */
-static inline Sxpr mkint(int i){
-    return OBJI(T_UINT, i);
-}
-
-/** Create a boolean sxpr.
- *
- * @param b value
- * @return sxpr
- */
-static inline Sxpr mkbool(int b){
-    return OBJI(T_BOOL, (b ? 1 : 0));
-}
-
-/* Constants used in parsing and printing. */
-#define k_list_open    "("
-#define c_list_open    '('
-#define k_list_close   ")"
-#define c_list_close   ')'
-#define k_true         "true"
-#define k_false        "false"
-
-#define c_var          '$'
-#define c_escape       '\\'
-#define c_single_quote '\''
-#define c_double_quote '"'
-#define c_string_open  c_double_quote
-#define c_string_close c_double_quote
-#define c_data_open    '['
-#define c_data_close   ']'
-#define c_binary       '*'
-#define c_eval         '!'
-#define c_concat_open  '{'
-#define c_concat_close '}'
-
-#endif /* ! _XEN_LIB_SXPR_H_ */
diff --git a/tools/lib/sxpr_parser.c b/tools/lib/sxpr_parser.c
deleted file mode 100644 (file)
index 16fec56..0000000
+++ /dev/null
@@ -1,897 +0,0 @@
-
-#ifdef __KERNEL__
-#  include <linux/config.h>
-#  include <linux/module.h>
-#  include <linux/kernel.h>
-#  include <linux/string.h>
-#  include <linux/errno.h>
-#else
-#  include <stdlib.h>
-#  include <errno.h>
-#endif
-
-#include "iostream.h"
-#include "lexis.h"
-#include "sxpr_parser.h"
-#include "sys_string.h"
-
-/** @file
- * Sxpr parsing.
- *
- * So that the parser does not leak memory, all sxprs constructed by
- * the parser must be freed on error.  On successful parse the sxpr
- * returned becomes the responsibility of the caller.
- *
- * @author Mike Wray <mike.wray@hpl.hp.com>
- */
-
-#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
-#define printf(fmt, args...)   IOStream_print(iostdout, fmt, ##args)
-
-static void reset(Parser *z);
-static int inputchar(Parser *p, char c);
-static int savechar(Parser *p, char c);
-extern void parse_error(Parser *in);
-extern void parse_error_id(Parser *in, ParseErrorId id);
-
-static int begin_start(Parser *p, char c);
-static int state_start(Parser *p, char c);
-static int end_start(Parser *p);
-
-static int begin_comment(Parser *p, char c);
-static int state_comment(Parser *p, char c);
-static int end_comment(Parser *p);
-
-static int begin_string(Parser *p, char c);
-static int state_string(Parser *p, char c);
-static int end_string(Parser *p);
-static int state_escape(Parser *p, char c);
-static int state_octal(Parser *p, char c);
-static int state_hex(Parser *p, char c);
-
-static int begin_atom(Parser *p, char c);
-static int state_atom(Parser *p, char c);
-static int end_atom(Parser *p);
-
-static int state_list(Parser *p, char c);
-static int begin_list(Parser *p, char c);
-static int end_list(Parser *p);
-
-/** Print a parse error.
- *
- * @param in parser
- * @param msg format followed by printf arguments
- */
-void eprintf(Parser *in, char *msg, ...){
-    va_list args;
-    if(in->error_out){
-        va_start(args, msg);
-        IOStream_vprint(in->error_out, msg, args);
-        va_end(args);
-    }
-}
-
-/** Print a parse warning.
- *
- * @param in parser
- * @param msg format followed by printf arguments
- */
-void wprintf(Parser *in, char *msg, ...){
-    va_list args;
-    if(in->error_out){
-        va_start(args, msg);
-        IOStream_vprint(in->error_out, msg, args);
-        va_end(args);
-    }
-}
-
-/*============================================================================*/
-
-/** Record defining the message for a parse error. */
-typedef struct {
-  ParseErrorId id;
-  char *message;
-} ParseError;
-
-/** Format for printing parse error messages. */
-#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s"
-
-/** Message catalog for the parse error codes. */
-static ParseError catalog[] = {
-  { PARSE_ERR_UNSPECIFIED,            "unspecified error" },
-  { PARSE_ERR_NOMEM,                  "out of memory" },
-  { PARSE_ERR_UNEXPECTED_EOF,         "unexpected end of input" },
-  { PARSE_ERR_TOKEN_TOO_LONG,         "token too long" },
-  { PARSE_ERR_INVALID_SYNTAX,         "syntax error" },
-  { PARSE_ERR_INVALID_ESCAPE,         "invalid escape" },
-  { 0, NULL }
-};
-
-/** Number of entries in the message catalog. */
-const static int catalog_n = sizeof(catalog)/sizeof(ParseError);
-
-void ParserState_free(ParserState *z){
-    if(!z) return;
-    objfree(z->val);
-    deallocate(z);
-}
-
-int ParserState_new(ParserStateFn *fn, ParserState *parent, ParserState **val){
-    int err = 0;
-    ParserState *z;
-    z = ALLOCATE(ParserState);
-    if(z){
-        z->fn = fn;
-        z->parent = parent;
-        z->val = ONULL;
-    } else {
-        err = -ENOMEM;
-    }
-    if(!err) *val = z;
-    return err;
-}
-
-/** Free a parser.
- * No-op if the parser is null.
- *
- * @param z parser 
- */
-void Parser_free(Parser *z){
-    if(!z) return;
-    objfree(z->val);
-    z->val = ONONE;
-    deallocate(z);
-}
-
-/** Create a new parser. The error stream defaults to null.
- */
-Parser * Parser_new(void){
-    Parser *z = ALLOCATE(Parser);
-    int err = -ENOMEM;
-  
-    if(!z) goto exit;
-    err = 0;
-    reset(z);
-  exit:
-    if(err){
-        Parser_free(z);
-        z = NULL;
-    }
-    return z;
-}
-
-/** Get the next character.
- * Records the character read in the parser,
- * and sets the line and character counts.
- *
- * @param p parser
- * @return error flag: 0 on success, non-zero on error
- */
-static int inputchar(Parser *p, char c){
-    int err = 0;
-    if(c=='\n'){
-        p->line_no++;
-        p->char_no = 0;
-    } else {
-        p->char_no++;
-    }
-    return err;
-}
-
-static int savechar(Parser *p, char c){
-    int err = 0;
-    if(p->buf_i >= p->buf_n){
-        err = -ENOMEM;
-        goto exit;
-    }
-    p->buf[p->buf_i] = c;
-    p->buf_i++;
-  exit:
-    return err;
-}
-
-int Parser_input_char(Parser *p, char c){
-    int err = 0;
-    if(at_eof(p)){
-        //skip;
-    } else {
-        inputchar(p, c);
-    }
-    if(!p->state){
-        err = begin_start(p, c);
-        if(err) goto exit;
-    }
-    err = p->state->fn(p, c);
-  exit:
-    return err;
-}
-
-int Parser_input_eof(Parser *p){
-    int err = 0;
-    p->eof = 1;
-    err = Parser_input_char(p, IOSTREAM_EOF);
-    return err;
-}
-
-int Parser_input(Parser *p, char *buf, int buf_n){
-    int err = 0;
-    int i = 0;
-    if(buf_n <= 0){
-        err = Parser_input_eof(p);
-        goto exit;
-    }
-    for(i = 0; i<buf_n; i++){
-        err = Parser_input_char(p, buf[i]);
-        if(err) goto exit;
-    }
-  exit:
-    err = (err < 0 ? err : buf_n);
-    return err;
-}
-
-int Parser_push(Parser *p, ParserStateFn *fn){
-    int err = 0;
-    err = ParserState_new(fn, p->state, &p->state);
-    return err;
-}
-        
-int Parser_pop(Parser *p){
-    int err = 0;
-    ParserState *s = p->state;
-    p->state = s->parent;
-    ParserState_free(s);
-    return err;
-}
-
-int Parser_return(Parser *p){
-    int err = 0;
-    Sxpr val = ONONE;
-    if(!p->state){
-        err = -EINVAL;
-        goto exit;
-    }
-    val = p->state->val;
-    p->state->val = ONONE;
-    err = Parser_pop(p);
-    if(err) goto exit;
-    if(p->state){
-        err = cons_push(&p->state->val, val);
-    } else {
-        val = nrev(val);
-        p->val = val;
-    }
-  exit:
-    if(err){
-        objfree(val);
-    }
-    return err;
-}
-
-/** Determine if a character is a separator.
- *
- * @param p parser
- * @param c character to test
- * @return 1 if a separator, 0 otherwise
- */
-static int is_separator(Parser *p, char c){
-    return in_sep_class(c);
-}
-
-/** Return the current token.
- * The return value points at the internal buffer, so
- * it must not be modified (or freed). Use copy_token() if you need a copy.
- *
- * @param p parser
- * @return token
- */
-char *peek_token(Parser *p){
-    return p->buf;
-}
-
-/** Return a copy of the current token.
- * The returned value should be freed when finished with.
- *
- * @param p parser
- * @return copy of token
- */
-char *copy_token(Parser *p){
-    return strdup(peek_token(p));
-}
-
-static int do_intern(Parser *p){
-    int err = 0;
-    Sxpr obj = intern(peek_token(p));
-    if(NOMEMP(obj)){
-        err = -ENOMEM;
-    } else {
-        p->state->val = obj;
-    }
-    return err;
-}
-
-static int do_string(Parser *p){
-    int err = 0;
-    Sxpr obj;
-    obj = string_new(peek_token(p));
-    if(NOMEMP(obj)){
-        err = -ENOMEM;
-    } else {
-        p->state->val = obj;
-    }
-    return err;
-}
-
-void newtoken(Parser *p){
-    memset(p->buf, 0, p->buf_n);
-    p->buf_i = 0;
-    p->tok_begin_line = p->line_no;
-    p->tok_begin_char = p->char_no;
-}
-
-int get_escape(char c, char *d){
-    int err = 0;
-    switch(c){
-    case 'a':            *d = '\a'; break;
-    case 'b':            *d = '\b'; break;
-    case 'f':            *d = '\f'; break;
-    case 'n':            *d = '\n'; break;
-    case 'r':            *d = '\r'; break;
-    case 't':            *d = '\t'; break;
-    case 'v':            *d = '\v'; break;
-    case c_escape:       *d = c_escape; break;
-    case c_single_quote: *d = c_single_quote; break;
-    case c_double_quote: *d = c_double_quote; break;
-    default:
-        err = -EINVAL;
-    }
-    return err;
-}
-
-
-int begin_start(Parser *p, char c){
-    return Parser_push(p, state_start);
-}
-
-int state_start(Parser *p, char c){
-    int err = 0;
-    if(at_eof(p)){
-        err = end_start(p);
-    } else if(in_space_class(c)){
-        //skip
-    } else if(in_comment_class(c)){
-        begin_comment(p, c);
-    } else if(c == c_list_open){
-        begin_list(p, c);
-    } else if(c == c_list_close){
-        parse_error(p);
-        err = -EINVAL;
-    } else if(in_string_quote_class(c)){
-        begin_string(p, c);
-    } else if(in_printable_class(c)){
-        begin_atom(p, c);
-    } else if(c == 0x04){
-        //ctrl-D, EOT: end-of-text.
-        Parser_input_eof(p);
-    } else {
-        parse_error(p);
-        err = -EINVAL;
-    }
-    return err;
-}
-
-int end_start(Parser *p){
-    int err = 0;
-    err = Parser_return(p);
-    return err;
-}
-
-int begin_comment(Parser *p, char c){
-    int err = 0;
-    err = Parser_push(p, state_comment);
-    if(err) goto exit;
-    err = inputchar(p, c);
-  exit:
-    return err;
-}
-
-int state_comment(Parser *p, char c){
-    int err = 0;
-    if(c == '\n' || at_eof(p)){
-        err = end_comment(p);
-    } else {
-        err = inputchar(p, c);
-    }
-    return err;
-}
-
-int end_comment(Parser *p){
-    return Parser_pop(p);
-}
-
-int begin_string(Parser *p, char c){
-    int err = 0;
-    err = Parser_push(p, state_string);
-    if(err) goto exit;
-    newtoken(p);
-    p->state->delim = c;
-  exit:
-    return err;
-}
-
-int state_string(Parser *p, char c){
-    int err = 0;
-    if(at_eof(p)){
-        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
-        err = -EINVAL;
-    } else if(c == p->state->delim){
-        err = end_string(p);
-    } else if(c == '\\'){
-        err = Parser_push(p, state_escape);
-    } else {
-        err = savechar(p, c);
-    }
-    return err;
-}
-
-int end_string(Parser *p){
-    int err = 0;
-    err = do_string(p);
-    if(err) goto exit;
-    err = Parser_return(p);
-  exit:
-    return err;
-}
-
-int state_escape(Parser *p, char c){
-    int err = 0;
-    char d;
-    if(at_eof(p)){
-        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
-        err = -EINVAL;
-        goto exit;
-    }
-    if(get_escape(c, &d) == 0){
-        err = savechar(p, d);
-        if(err) goto exit;
-        err = Parser_pop(p);
-    } else if(c == 'x'){
-        p->state->fn = state_hex;
-        p->state->ival = 0;
-        p->state->count = 0;
-    } else {
-        p->state->fn = state_octal;
-        p->state->ival = 0;
-        p->state->count = 0;
-        err = Parser_input_char(p, c);
-    }
-  exit:
-    return err;
-}
-
-int octaldone(Parser *p){
-    int err = 0;
-    char d = (char)(p->state->ival & 0xff);
-    err = Parser_pop(p);
-    if(err) goto exit;
-    err = Parser_input_char(p, d);
-  exit:
-    return err;
-}
-
-int octaldigit(Parser *p, char c){
-    int err = 0;
-    p->state->ival *= 8;
-    p->state->ival += c - '0'; 
-    p->state->count++;
-    if(err) goto exit;
-    if(p->state->ival < 0 || p->state->ival > 0xff){
-        parse_error(p);
-        err = -EINVAL;
-        goto exit;
-    }
-    if(p->state->count == 3){
-        err = octaldone(p);
-    }
-  exit:
-    return err;
-}
-
-int state_octal(Parser *p, char c){
-    int err = 0;
-    if(at_eof(p)){
-        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
-        err = -EINVAL;
-        goto exit;
-    } else if('0' <= c && c <= '7'){
-        err = octaldigit(p, c);
-    } else {
-        err = octaldone(p);
-        if(err) goto exit;
-        Parser_input_char(p, c);
-    }
-  exit:
-    return err;
-}
-
-int hexdone(Parser *p){
-    int err = 0;
-    char d = (char)(p->state->ival & 0xff);
-    err = Parser_pop(p);
-    if(err) goto exit;
-    err = Parser_input_char(p, d);
-  exit:
-    return err;
-}
-    
-int hexdigit(Parser *p, char c, char d){
-    int err = 0;
-    p->state->ival *= 16;
-    p->state->ival += c - d; 
-    p->state->count++;
-    if(err) goto exit;
-    if(p->state->ival < 0 || p->state->ival > 0xff){
-        parse_error(p);
-        err = -EINVAL;
-        goto exit;
-    }
-    if(p->state->count == 2){
-        err = hexdone(p);
-    }
-  exit:
-    return err;
-}
-    
-int state_hex(Parser *p, char c){
-    int err = 0;
-    if(at_eof(p)){
-        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
-        err = -EINVAL;
-        goto exit;
-    } else if('0' <= c && c <= '9'){
-        err = hexdigit(p, c, '0');
-    } else if('A' <= c && c <= 'F'){
-        err = hexdigit(p, c, 'A');
-    } else if('a' <= c && c <= 'f'){
-        err = hexdigit(p, c, 'a');
-    } else if(p->state->count){
-        err =hexdone(p);
-        if(err) goto exit;
-        Parser_input_char(p, c);
-    }
-  exit:
-    return err;
-}
-
-int begin_atom(Parser *p, char c){
-    int err = 0;
-    err = Parser_push(p, state_atom);
-    if(err) goto exit;
-    newtoken(p);
-    err = savechar(p, c);
-  exit:
-    return err;
-}
-
-int state_atom(Parser *p, char c){
-    int err = 0;
-    if(at_eof(p)){
-        err = end_atom(p);
-    } else if(is_separator(p, c) ||
-              in_space_class(c) ||
-              in_comment_class(c)){
-        err = end_atom(p);
-        if(err) goto exit;
-        err = Parser_input_char(p, c);
-    } else {
-        err = savechar(p, c);
-    }
-  exit:
-    return err;
-}
-
-int end_atom(Parser *p){
-    int err = 0;
-    err = do_intern(p);
-    if(err) goto exit;
-    err = Parser_return(p);
-  exit:
-    return err;
-}
-
-int state_list(Parser *p, char c){
-    int err = 0;
-    if(at_eof(p)){
-        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
-        err = -EINVAL;
-    } else if(c == c_list_close){
-        p->state->val = nrev(p->state->val);
-        err = end_list(p);
-    } else {
-        err = state_start(p, c);
-    }
-    return err;
-    
-}
-
-int begin_list(Parser *p, char c){
-    return Parser_push(p, state_list);
-}
-
-int end_list(Parser *p){
-    return Parser_return(p);
-}
-
-/** Reset the fields of a parser to initial values.
- *
- * @param z parser
- */
-static void reset(Parser *z){
-  IOStream *error_out = z->error_out;
-  int flags = z->flags;
-  zero(z, sizeof(Parser));
-  z->buf_n = sizeof(z->buf) - 1;
-  z->buf_i = 0;
-  z->line_no = 1;
-  z->char_no = 0;
-  z->error_out = error_out;
-  z->flags = flags;
-}
-
-/** Set the parser error stream.
- * Parse errors are reported on the the error stream if it is non-null.
- * 
- * @param z parser
- * @param error_out error stream
- */
-void set_error_stream(Parser *z, IOStream *error_out){
-  if(z){
-    z->error_out = error_out;
-  }
-}
-
-/** Get the parser error message for an error code.
- *
- * @param id error code
- * @return error message (empty string if the code is unknown)
- */
-static char *get_message(ParseErrorId id){
-  int i;
-  for(i=0; i<catalog_n; i++){
-    if(id == catalog[i].id){
-      return catalog[i].message;
-    }
-  }
-  return "";
-}
-
-/** Get the line number.
- *
- * @param in parser
- */
-int get_line(Parser *in){
-  return in->line_no;
-}
-
-/** Get the column number.
- *
- * @param in parser
- */
-int get_column(Parser *in){
-  return in->char_no;
-}
-
-/** Get the line number the current token started on.
- *
- * @param in parser
- */
-int get_tok_line(Parser *in){
-  return in->tok_begin_line;
-}
-
-/** Get the column number the current token started on.
- *
- * @param in parser
- */
-int get_tok_column(Parser *in){
-  return in->tok_begin_char;
-}
-
-/** Report a parse error.
- * Does nothing if the error stream is null or there is no error.
- *
- * @param in parser
- */
-static void report_error(Parser *in){
-  if(in->error_out && in->err){
-    char *msg = get_message(in->err);
-    char *tok = peek_token(in);
-    IOStream_print(in->error_out, PARSE_ERR_FMT,
-                  get_tok_line(in), get_tok_column(in), msg);
-    if(tok && tok[0]){
-        IOStream_print(in->error_out, " '%s'", tok);
-    }
-    IOStream_print(in->error_out, "\n");
-  }
-}
-
-/** Get the error message for the current parse error code.
- * Does nothing if there is no error.
- *
- * @param in parser
- * @param buf where to place the message
- * @param n maximum number of characters to place in buf
- * @return current error code (zero for no error)
- */
-int parse_error_message(Parser *in, char *buf, int n){
-    if(in->err){
-        char *msg = get_message(in->err);
-        snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg);
-    }
-    return in->err;
-}
-
-/** Flag an unspecified parse error. All subsequent reads will fail.
- *
- * @param in parser
- */
-void parse_error(Parser *in){
-    parse_error_id(in, PARSE_ERR_INVALID_SYNTAX);
-}
-
-/** Flag a parse error. All subsequent reads will fail.
- * Does not change the parser error code if it is already set.
- *
- * @param in parser
- * @param id error code
- */
-void parse_error_id(Parser *in, ParseErrorId id){
-    if(!in->err){
-        in->err = id;
-        report_error(in);
-    }
-}
-
-/** Test if the parser's error flag is set.
- *
- * @param in parser
- * @return 1 if set, 0 otherwise
- */
-int has_error(Parser *in){
-    return (in->err > 0);
-}
-
-/** Test if the parser is at end of input.
- *
- * @param in parser
- * @return 1 if at EOF, 0 otherwise
- */
-int at_eof(Parser *p){
-    return p->eof;
-}
-
-#ifdef SXPR_PARSER_MAIN
-/* Stuff for standalone testing. */
-
-#include "file_stream.h"
-#include "string_stream.h"
-
-int stringof(Sxpr exp, char **s){
-    int err = 0;
-    if(ATOMP(exp)){
-        *s = atom_name(exp);
-    } else if(STRINGP(exp)){
-        *s = string_string(exp);
-    } else {
-        err = -EINVAL;
-        *s = NULL;
-    }
-    return err;
-}
-
-int child_string(Sxpr exp, Sxpr key, char **s){
-    int err = 0;
-    Sxpr val = sxpr_child_value(exp, key, ONONE);
-    err = stringof(val, s);
-    return err;
-}
-
-int intof(Sxpr exp, int *v){
-    int err = 0;
-    char *s;
-    unsigned long l;
-    if(INTP(exp)){
-        *v = OBJ_INT(exp);
-    } else {
-        err = stringof(exp, &s);
-        if(err) goto exit;
-        err = convert_atoul(s, &l);
-        *v = (int)l;
-    }
- exit:
-    return err;
-}
-
-int child_int(Sxpr exp, Sxpr key, int *v){
-    int err = 0;
-    Sxpr val = sxpr_child_value(exp, key, ONONE);
-    err = intof(val, v);
-    return err;
-}
-
-int eval_vnet(Sxpr exp){
-    int err = 0;
-    Sxpr oid = intern("id");
-    int id;
-    err = child_int(exp, oid, &id);
-    if(err) goto exit;
-    dprintf("> vnet id=%d\n", id);
- exit:
-    dprintf("< err=%d\n", err);
-    return err;
-}
-
-int eval_connect(Sxpr exp){
-    int err = 0;
-    Sxpr ovif = intern("vif");
-    Sxpr ovnet = intern("vnet");
-    char *vif;
-    int vnet;
-
-    err = child_string(exp, ovif, &vif);
-    if(err) goto exit;
-    err = child_int(exp, ovnet, &vnet);
-    if(err) goto exit;
-    dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
- exit:
-    dprintf("< err=%d\n", err);
-    return err;
-}
-
-int eval(Sxpr exp){
-    int err = 0;
-    Sxpr oconnect = intern("connect");
-    Sxpr ovnet = intern("vnet");
-    
-    if(sxpr_elementp(exp, ovnet)){
-        err = eval_vnet(exp);
-    } else if(sxpr_elementp(exp, oconnect)){
-        err = eval_connect(exp);
-    } else {
-        err = -EINVAL;
-    }
-    return err;
-}
-
-/** Main program for testing.
- * Parses input and prints it.
- *
- * @param argc number of arguments
- * @param argv arguments
- * @return error code
- */
-int main(int argc, char *argv[]){
-    Parser *pin;
-    int err = 0;
-    char buf[1024];
-    int k;
-    Sxpr obj, l, x;
-
-    pin = Parser_new();
-    set_error_stream(pin, iostdout);
-    dprintf("> parse...\n");
-    while(1){
-        k = fread(buf, 1, 1024, stdin);
-        err = Parser_input(pin, buf, k);
-        dprintf("> Parser_input=%d\n", err);
-        if(k <= 0) break;
-    }
-    obj = pin->val;
-    for(l = obj ; CONSP(l); l = CDR(l)){
-        x = CAR(l);
-        objprint(iostdout, x, 0); printf("\n");
-        eval(x);
-    }
-    dprintf("> err=%d\n", err);
-    return 0;
-}
-#endif
diff --git a/tools/lib/sxpr_parser.h b/tools/lib/sxpr_parser.h
deleted file mode 100644 (file)
index 7296312..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or  (at your option) any later version. This library is 
- * distributed in the  hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#ifndef _XEN_LIB_SXPR_PARSER_H_
-#define _XEN_LIB_SXPR_PARSER_H_
-
-#include "sxpr.h"
-#include "iostream.h"
-
-/** @file
- * Sxpr parsing definitions.
- */
-
-/** Size of a parser input buffer.
- * Tokens read must fit into this size (including trailing null).
- */
-#define PARSER_BUF_SIZE 1024
-
-struct Parser;
-typedef int ParserStateFn(struct Parser *, char c);
-
-typedef struct ParserState {
-    struct ParserState *parent;
-    Sxpr val;
-    int ival;
-    int count;
-    char delim;
-    ParserStateFn *fn;
-} ParserState;
-
-/** Structure representing an input source for the parser.
- * Can read from any IOStream implementation.
- */
-typedef struct Parser {
-    Sxpr val;
-    /** Error reporting stream (null for no reports). */
-    IOStream *error_out;
-    int eof;
-    /** Error flag. Non-zero if there has been a read error. */
-    int err;
-    /** Line number on input (from 1). */
-    int line_no;
-    /** Column number of input (reset on new line). */
-    int char_no;
-    /** Lookahead character. */
-    char c;
-    /** Buffer for reading tokens. */
-    char buf[PARSER_BUF_SIZE];
-    /** Size of token buffer. */
-    int buf_n;
-    int buf_i;
-    /** Line the last token started on. */
-    int tok_begin_line;
-    /** Character number the last token started on. */
-    int tok_begin_char;
-    /** Parsing flags. */
-    int flags;
-    ParserState *state;
-} Parser;
-
-/** Parser error codes. */
-typedef enum {
-    PARSE_ERR_NONE=0,
-    PARSE_ERR_UNSPECIFIED,
-    PARSE_ERR_NOMEM,
-    PARSE_ERR_UNEXPECTED_EOF,
-    PARSE_ERR_TOKEN_TOO_LONG,
-    PARSE_ERR_INVALID_SYNTAX,
-    PARSE_ERR_INVALID_ESCAPE,
-} ParseErrorId;
-
-
-/** Parser flags. */
-//enum {
-//};
-
-/** Raise some parser flags.
- *
- * @param in parser
- * @param flags flags mask
- */
-inline static void parser_flags_raise(Parser *in, int flags){
-    in->flags |= flags;
-}
-
-/** Lower some parser flags.
- *
- * @param in parser
- * @param flags flags mask
- */
-inline static void parser_flags_lower(Parser *in, int flags){
-    in->flags &= ~flags;
-}
-
-/** Clear all parser flags.
- *
- * @param in parser
- */
-inline static void parser_flags_clear(Parser *in){
-    in->flags = 0;
-}
-
-extern void Parser_free(Parser *z);
-extern Parser * Parser_new(void);
-extern int Parser_input(Parser *p, char *buf, int buf_n);
-extern int Parser_input_eof(Parser *p);
-
-extern int parse_error_message(Parser *in, char *buf, int n);
-extern int has_error(Parser *in);
-extern int at_eof(Parser *in);
-
-#endif /* ! _XEN_LIB_SXPR_PARSER_H_ */
diff --git a/tools/lib/sys_ctype.h b/tools/lib/sys_ctype.h
deleted file mode 100644 (file)
index 1dc6cf2..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _XENO_SYS_CTYPE_H_
-#define _XENO_SYS_CTYPE_H_
-/** @file
- ** Replacement for ctype include that can be used
- * from user or kernel code.
- */
-#ifdef __KERNEL__
-#  include <linux/ctype.h>
-#else
-#  include <ctype.h>
-#endif
-#endif /* ! _XENO_SYS_CTYPE_H_ */
diff --git a/tools/lib/sys_net.c b/tools/lib/sys_net.c
deleted file mode 100644 (file)
index 0e7ac5d..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or  (at your option) any later version. This library is 
- * distributed in the  hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#include "sys_net.h"
-#include "sys_string.h"
-
-/** @file
- * All network data are kept in network order and only converted to
- * host order for display. Network data includes IP addresses, port numbers and
- * network masks.
- */
-
-/** Maximum value for a port. */
-#define PORT_MAX 0xffff
-
-/** Convert a number of bits to a network mask
- * for IP addresses. The number of bits must
- * be in the range 1-31.
- *
- * @param n number of bits to set in the mask
- * @return value with n high bits set (in network order)
- */
-unsigned long bits_to_mask(int n){
-    unsigned long mask = (n ? (1 << 31) : 0);
-    int i;
-    for(i=1; i<n; i++){
-        mask |= (mask >> 1);
-    }
-    return htonl(mask);
-}
-
-/** Convert a network mask to a number of bits.
- *
- * @param mask network mask in network order
- * @return number of bits in mask
- */
-int mask_to_bits(unsigned long mask){
-    // Start with n set to the number of bits in the mask. Then reduce n by
-    // the number of low zero bits in the mask.
-    int n = 32;
-    for(mask = ntohl(mask);
-        (mask & 1)==0 && n>0;
-        mask >>= 1){
-        n--;
-    }
-    return n;
-}
-
-/** Get the index of the first occurrence of a character in a string.
- * Stops at end of string or after n characters.
- *
- * @param s input string
- * @param n maximum number of charactes to search
- * @param c character to look for
- * @return index of first occurrence, -1 if not found
- */
-inline static int indexof(const char *s, int n, char c){
-    int i;
-    for(i=0; i<n && *s; i++, s++){
-        if(*s == c) return i;
-    }
-    return -1;
-}
-
-/** Convert an IPv4 address in dot notation into an unsigned long (in network order).
- *
- * @param s input string
- * @param address where to put the address
- * @return 0 on success, -1 on error
- */
-int get_inet_addr(const char *s, unsigned long *address){
-    // Number of bits in a byte.
-    const int BYTE_BITS = 8;
-    // Number of bytes in a word.
-    const int WORD_BYTES = 4;
-    // Max value for a component of an address.
-    const int ADDR_MAX  = 255;
-    // Separator for components of an address.
-    const char dot = '.';
-
-    int n;
-    unsigned long addr = 0;
-    unsigned long v;
-    int i;
-    int err = -1;
-    // Bit shift for the current byte.
-    int shift = BYTE_BITS * (WORD_BYTES - 1);
-    char buf[64];
-
-    n = strlen(s);
-    if(n >= sizeof(buf)){
-        goto exit;
-    }
-    for(i=0; i < WORD_BYTES; i++){
-        int idx = indexof(s, n, dot);
-        idx = (idx < 0 ? strlen(s) : idx);
-        strncpy(buf, s, idx); buf[idx]='\0';
-        if(convert_atoul(buf, &v)){
-            goto exit;
-        }
-        if(v < 0 || v > ADDR_MAX){
-            goto exit;
-        }
-        addr |= (v << shift);
-        if(idx == n) break;
-        shift -= BYTE_BITS;
-        s += idx+1;
-    }
-    err = 0;
-  exit:
-    addr = htonl(addr);
-    *address = (err ? 0 : addr);
-    return err;
-}
-
-#ifdef __KERNEL__
-/** Convert an address in network order to IPv4 dot notation.
- * The return value is a static buffer which is overwritten on each call.
- *
- * @param inaddr address (in network order)
- * @return address in dot notation
- */
-char *inet_ntoa(struct in_addr inaddr){
-    static char address[16] = {};
-    uint32_t addr = ntohl(inaddr.s_addr);
-    snprintf(address, sizeof(address), "%d.%d.%d.%d",
-            (unsigned)((addr >> 24) & 0xff),
-            (unsigned)((addr >> 16) & 0xff),
-            (unsigned)((addr >>  8) & 0xff),
-            (unsigned)((addr      ) & 0xff));
-    return address;
-}
-
-
-/** Convert a string in IPv4 dot notation to an int in network order.
- *
- * @param address address in dot notation
- * @param inp result of conversion (in network order)
- * @return 0 on success, error code on error
- */
-int inet_aton(const char *address, struct in_addr *inp){
-    int err = 0; 
-    unsigned long addr;
-    
-    err = get_inet_addr(address, &addr);
-    if(err) goto exit;
-    inp->s_addr = addr;
-  exit:
-    return err;
-}
-#endif
-
-/** Convert a hostname or IPv4 address string to an address in network order.
- *
- * @param name input hostname or address string
- * @param address where to put the address
- * @return 1 if address found OK, 0 otherwise
- */
-int get_host_address(const char *name, unsigned long *address){
-#ifdef __KERNEL__
-    return get_inet_addr(name, address) == 0;
-#else
-    struct hostent *host = gethostbyname(name);
-    if(!host){
-        return 0;
-    }
-    *address = ((struct in_addr *)(host->h_addr))->s_addr;
-    return 1;
-#endif
-}
-
-/** Convert a service name to a port (in network order).
- *
- * @param name service name
- * @param port where to put the port
- * @return 1 if service port found OK, 0 otherwise
- */
-int get_service_port(const char *name, unsigned long *port){
-#ifdef __KERNEL__
-    return 0;
-#else
-    struct servent *service;
-    service = getservbyname(name, 0);
-    if(!service){
-        return 0;
-    }
-    *port = service->s_port;
-    return 1;
-#endif
-}
-
-/** Convert a port number (in network order) to a service name.
- *
- * @param port the port number
- * @return service name if found OK, 0 otherwise
- */
-char *get_port_service(unsigned long port){
-#ifdef __KERNEL__
-    return 0;
-#else
-    struct servent *service = getservbyport(port, 0);
-    return (service ? service->s_name : 0);
-#endif
-}
-
-/** Convert a decimal integer or service name to a port (in network order).
- *
- * @param s input to convert
- * @param port where to put the port
- * @return 1 if port found OK, 0 otherwise
- */
-int convert_service_to_port(const char *s, unsigned long *port){
-    int ok = 0;
-    unsigned long value;
-    if(convert_atoul(s, &value)){
-        ok = get_service_port(s, &value);
-    } else {
-        ok = (0 <= value) && (value <= PORT_MAX);
-        value = htons((unsigned short)value);
-    }
-    *port = (ok ? value : 0);
-    return ok;
-}
-
-#define MAC_ELEMENT_N  6 // Number of elements in a MAC address.
-#define MAC_DIGIT_N    2 // Number of digits in an element in a MAC address.
-#define MAC_LENGTH    17 //((MAC_ELEMENT_N * MAC_DIGIT_N) + MAC_ELEMENT_N - 1)
-
-/** Convert a mac address from a string of the form
- * XX:XX:XX:XX:XX:XX to numerical form (an array of 6 unsigned chars).
- * Each X denotes a hex digit: 0..9, a..f, A..F.
- * Also supports using '-' as the separator instead of ':'.
- *
- * @param mac_in string to convert
- * @param mac destination for the value
- * @return 0 on success, -1 on error
- */
-int mac_aton(const char *mac_in, unsigned char *mac){
-    int err = 0;
-    int i, j;
-    const char *p;
-    char sep = 0;
-    unsigned char d;
-    if(!mac_in || strlen(mac_in) != MAC_LENGTH){
-        err = -1;
-        goto exit;
-    }
-    for(i = 0, p = mac_in; i < MAC_ELEMENT_N; i++){
-        d = 0;
-        if(i){
-            if(!sep){
-                if(*p == ':' || *p == '-') sep = *p;
-            }
-            if(sep && *p == sep){
-                p++;
-            } else {
-                err = -1;
-                goto exit;
-            }
-        }
-        for(j = 0; j < MAC_DIGIT_N; j++, p++){
-            if(j) d <<= 4;
-            if(*p >= '0' && *p <= '9'){
-                d += (*p - '0');
-            } else if(*p >= 'A' && *p <= 'F'){
-                d += (*p - 'A') + 10;
-            } else if(*p >= 'a' && *p <= 'f'){
-                d += (*p - 'a') + 10;
-            } else {
-                err = -1;
-                goto exit;
-            }
-        }
-        mac[i] = d;
-    }
-  exit:
-    return err;
-}
-
-/** Convert a MAC address from numerical form to a string.
- *
- * @param mac address to convert
- * @return static string value
- */
-char *mac_ntoa(const unsigned char *mac){
-    static char buf[MAC_LENGTH + 1];
-    int buf_n = sizeof(buf);
-
-    memset(buf, buf_n, 0);
-    snprintf(buf, buf_n, "%02x:%02x:%02x:%02x:%02x:%02x",
-             mac[0], mac[1], mac[2],
-             mac[3], mac[4], mac[5]);
-    buf[buf_n - 1] = '\0';
-    return buf;
-}
diff --git a/tools/lib/sys_net.h b/tools/lib/sys_net.h
deleted file mode 100644 (file)
index da6c1e8..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _XEN_LIB_SYS_NET_H_
-#define _XEN_LIB_SYS_NET_H_
-/** @file
- *
- * Replacement for standard network includes.
- * Works in user or kernel code.
- */
-
-extern int get_inet_addr(const char *s, unsigned long *address);
-extern unsigned long bits_to_mask(int n);
-extern int mask_to_bits(unsigned long mask);
-extern int get_host_address(const char *name, unsigned long *address);
-extern int get_service_port(const char *name, unsigned long *port);
-extern char *get_port_service(unsigned long port);
-extern int convert_service_to_port(const char *s, unsigned long *port);
-
-#ifdef __KERNEL__
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h> 
-
-#ifndef htonl
-#define htonl(x) __constant_htonl(x)
-#endif
-
-#ifndef ntohl
-#define ntohl(x) __constant_ntohl(x)
-#endif
-
-#ifndef htons
-#define htons(x) __constant_htons(x)
-#endif
-
-#ifndef ntohs
-#define ntohs(x) __constant_ntohs(x)
-#endif
-
-#include <linux/in.h>
-extern char *inet_ntoa(struct in_addr inaddr);
-extern int inet_aton(const char *address, struct in_addr *inp);
-
-#else
-
-#include <limits.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-
-#endif
-
-extern char *mac_ntoa(const unsigned char *macaddr);
-extern int mac_aton(const char *addr, unsigned char *macaddr);
-
-#endif /* !_SP_SYS_NET_H_ */
-
-
-
diff --git a/tools/lib/sys_string.c b/tools/lib/sys_string.c
deleted file mode 100644 (file)
index 13a90df..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifdef __KERNEL__
-#  include <linux/config.h>
-#  include <linux/module.h>
-#  include <linux/kernel.h>
-#  include <linux/errno.h>
-#else
-#  include <errno.h>
-#endif
-
-#include "allocate.h"
-#include "sys_string.h"
-
-/** Set the base to use for converting a string to a number.  Base is
- * hex if starts with 0x, otherwise decimal.
- *
- * @param s input string
- * @param base where to put the base
- * @return rest of s to parse as a number
- */
-inline static const char * convert_set_base(const char *s, int *base){
-    *base = 10;
-    if(s){
-        if(*s=='0'){
-            s++;
-            if(*s=='x' || *s=='X'){
-                *base = 16;
-                s++;
-            }
-        }
-    }
-    return s;
-}
-
-/** Get the numerical value of a digit in the given base.
- *
- * @param c digit character
- * @param base to use
- * @return numerical value of digit in range 0..base-1 or
- * -1 if not in range for the base
- */
-inline static int convert_get_digit(char c, int base){
-    int d;
-
-    if('0'<=c  && c<='9'){
-        d = c - '0';
-    } else if('a'<=c && c<='f'){
-        d = c - 'a' + 10;
-    } else if('A'<=c && c<='F'){
-        d = c - 'A' + 10;
-    } else {
-        d = -1;
-    }
-    return (d < base ? d : -1);
-}
-
-/** Convert a string to an unsigned long by parsing it as a number.
- * Will accept hex or decimal in usual C syntax.
- *
- * @param str input string
- * @param val where to put the result
- * @return 0 if converted OK, negative otherwise
- */
-int convert_atoul(const char *str, unsigned long *val){
-    int err = 0;
-    unsigned long v = 0;
-    int base;
-    const char *s = str;
-
-    if(!s) {
-        err = -EINVAL;
-        goto exit;
-    }
-    s = convert_set_base(s, &base);
-    for( ; !err && *s; s++){
-        int digit = convert_get_digit(*s, base);
-        if(digit<0){
-            err = -EINVAL;
-            goto exit;
-        }
-        v *= base;
-        v += digit;
-    } 
-  exit:
-    *val = (err ? 0 : v);
-    return err;
-}
-
-/** Combine a directory path with a relative path to produce
- * a new path.
- *
- * @param s directory path
- * @param t relative path
- * @return new combined path s/t
- */
-int path_concat(char *s, char *t, char **val){
-    int err = 0;
-    int sn, tn, vn;
-    char *v;
-    sn = strlen(s);
-    if(sn > 0 && s[sn-1] == '/'){
-        sn--;
-    }
-    tn = strlen(t);
-    if(tn > 0 && t[0] == '/'){
-        tn--;
-    }
-    vn = sn+tn+1;
-    v = (char*)allocate(vn+1);
-    if(!v){
-        err = -ENOMEM;
-        goto exit;
-    }
-    strncpy(v, s, sn);
-    v[sn] = '/';
-    strncpy(v+sn+1, t, tn);
-    v[vn] = '\0';
-  exit:
-    *val = (err ? NULL : v);
-    return err;    
-}
diff --git a/tools/lib/sys_string.h b/tools/lib/sys_string.h
deleted file mode 100644 (file)
index f39935f..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _XEN_LIB_SYS_STRING_H_
-#define _XEN_LIB_SYS_STRING_H_
-/** @file
- * Replacement for standard string includes.
- * Works in user or kernel code.
- */
-/*============================================================================*/
-#ifdef __KERNEL__
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <stdarg.h>
-#include "allocate.h"
-
-#if 0
-static inline int tolower(int c){
-    return (c>='A' && c<='Z' ? (c-'A')+'a' : c);
-}
-#endif
-
-static inline int isalpha(int c){
-    return (c>='A' && c<='Z') || (c>='a' && c<='z');
-}
-
-static inline int isdigit(int c){
-   return (c>='0' && c<='9');
-}
-
-#if 0
-static inline int strcasecmp(const char *s1, const char *s2){
-       int c1, c2;
-
-       do {
-               c1 = tolower(*s1++);
-               c2 = tolower(*s2++);
-       } while (c1 && c1 == c2);
-       return c1 - c2;
-}
-#endif
-
-static inline char * strdup(const char *s){
-    int n = (s ? 1+strlen(s) : 0);
-    char *copy = (n ? allocate(n) : NULL);
-    if(copy){
-        strcpy(copy, s);
-    }
-    return copy;
-}
-
-/*============================================================================*/
-#else
-#include <string.h>
-#include <stdio.h>
-
-#ifndef _GNU_SOURCE
-static inline size_t strnlen(const char *s, size_t n){
-    int k = 0;
-    if(s){
-       for(k=0; *s && k<n; s++, k++){}
-    }
-    return k;
-}
-#endif
-
-#endif
-/*============================================================================*/
-
-extern int convert_atoul(const char *s, unsigned long *v);
-extern int path_concat(char *s, char *t, char **val);
-
-#endif /* !_XEN_LIB_SYS_STRING_H_ */
diff --git a/tools/lib/xdr.c b/tools/lib/xdr.c
deleted file mode 100644 (file)
index dfb91f2..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/* $Id: xdr.c,v 1.3 2003/09/29 13:40:00 mjw Exp $ */
-#include "xdr.h"
-#include <errno.h>
-/** @file
- * XDR packer/unpacker for elements.
- *
- * string -> [T_STRING] [len:u32] <len bytes>
- * atom   -> [T_ATOM]   [len:u32] <len bytes>
- * uint   -> [T_UINT]   [value]
- * cons   -> [T_CONS]   <car> <cdr>
- * null   -> [T_NULL]
- * none   -> [T_NONE]
- * bool   -> [T_BOOL]   { 0:u8 | 1:u8 }
- *
- * types packed as u16.
- *
- * So (a b c) -> [T_CONS] a [T_CONS] b [T_CONS] c [T_NULL]
- *    ()      -> [T_NULL]
- */
-
-int pack_bool(IOStream *io, int x){
-    int err=0;
-    err = IOStream_print(io, "%c", 0xff & x);
-    if(err > 0) err = 0;
-    return err;
-}
-
-int unpack_bool(IOStream *io, int *x){
-    int err = 0;
-    int c;
-    c = IOStream_getc(io);
-    *x = (c < 0 ? 0 : c);
-    err = IOStream_error(io);
-    if(c < 0 && !err) err = -EIO;
-    return err;
-}
-
-int pack_ushort(IOStream *io, unsigned short x){
-    int err=0;
-    err = IOStream_print(io, "%c%c",
-                         0xff & (x >>  8),
-                         0xff & (x      ));
-    if(err > 0) err = 0;
-    return err;
-}
-
-int unpack_ushort(IOStream *io, unsigned short *x){
-    int err = 0;
-    int i, c = 0;
-    *x = 0;
-    for(i = 0; i< 2; i++){
-        c = IOStream_getc(io);
-        if(c < 0) break;
-        *x <<= 8;
-        *x |= (0xff & c);
-    }
-    err = IOStream_error(io);
-    if(c < 0 && !err) err = -EIO;
-    return err;
-}
-
-int pack_uint(IOStream *io, unsigned int x){
-    int err=0;
-    err = IOStream_print(io, "%c%c%c%c",
-                         0xff & (x >> 24),
-                         0xff & (x >> 16),
-                         0xff & (x >>  8),
-                         0xff & (x      ));
-    if(err > 0) err = 0;
-    return err;
-}
-
-int unpack_uint(IOStream *io, unsigned int *x){
-    int err = 0;
-    int i, c = 0;
-    *x = 0;
-    for(i = 0; i< 4; i++){
-        c = IOStream_getc(io);
-        if(c < 0) break;
-        *x <<= 8;
-        *x |= (0xff & c);
-    }
-    err = IOStream_error(io);
-    if(c < 0 && !err) err = -EIO;
-    return err;
-}
-
-int pack_string(IOStream *io, Sxpr x){
-    int err = 0;
-    int n = string_length(x);
-    char *s = string_string(x);
-    int i;
-    err = pack_uint(io, n);
-    if(err) goto exit;
-    for(i = 0; i < n; i++){
-        err = IOStream_print(io, "%c", s[i]);
-        if(err < 0) break;
-    }
-    if(err > 0) err = 0;
-  exit:
-    return err;
-}
-
-int unpack_string(IOStream *io, Sxpr *x){
-    int err;
-    unsigned int n;
-    int i, c = 0;
-    char *s;
-    Sxpr val = ONONE;
-    
-    err = unpack_uint(io, &n);
-    if(err) goto exit;
-    val = halloc(n+1, T_STRING);
-    if(NOMEMP(val)){
-        err = -ENOMEM;
-        goto exit;
-    }
-    s = string_string(val);
-    for(i=0; i<n; i++){
-        c = IOStream_getc(io);
-        if(c < 0) break;
-        s[i] = (char)c;
-    }
-    s[n] = '\0';
-  exit:
-    err = IOStream_error(io);
-    if(c < 0 && !err) err = -EIO;
-    if(err){
-        objfree(val);
-        val = ONONE;
-    }
-    *x = val;
-    return err;
-}
-
-int pack_cons(IOStream *io, Sxpr x){
-    int err = 0;
-    err = pack_sxpr(io, CAR(x));
-    if(err) goto exit;
-    err = pack_sxpr(io, CDR(x));
-  exit:
-    return err;
-}
-
-int unpack_cons(IOStream *io, Sxpr *x){
-    int err = 0;
-    Sxpr u = ONONE, v = ONONE, val = ONONE;
-    err = unpack_sxpr(io, &u);
-    if(err) goto exit;
-    err = unpack_sxpr(io, &v);
-    if(err) goto exit;
-    val = cons_new(u, v);
-    if(NOMEMP(val)){
-        err = -ENOMEM;
-    }
-  exit:
-    if(err){
-        objfree(u);
-        objfree(v);
-        val = ONONE;
-    }        
-    *x = val;
-    return err;
-}
-
-int pack_sxpr(IOStream *io, Sxpr x){
-    int err = 0;
-    unsigned short type = get_type(x);
-    err = pack_ushort(io, type);
-    if(err) goto exit;
-    switch(type){
-    case T_NULL:
-        break;
-    case T_NONE:
-        break;
-        break;
-    case T_BOOL:
-        err = pack_bool(io, get_ul(x));
-        break;
-    case T_CONS:
-        err = pack_cons(io, x);
-        break;
-    case T_ATOM:
-        err = pack_string(io, OBJ_ATOM(x)->name);
-        break;
-    case T_STRING:
-        err = pack_string(io, x);
-        break;
-    case T_UINT:
-        err = pack_uint(io, get_ul(x));
-        break;
-    default:
-        err = -EINVAL;
-        IOStream_print(iostderr, "%s> invalid type %d\n", __FUNCTION__, type);
-        break;
-    }
-  exit:
-    return err;
-}
-
-int unpack_sxpr(IOStream *io, Sxpr *x){
-    int err = 0;
-    unsigned short type;
-    unsigned int u;
-    Sxpr val = ONONE, y;
-
-    err = unpack_ushort(io, &type);
-    if(err) goto exit;
-    switch(type){
-    case T_NULL:
-        val = ONULL;
-        break;
-    case T_NONE:
-        val = ONONE;
-        break;
-    case T_CONS:
-        err = unpack_cons(io, &val);
-        break;
-    case T_BOOL:
-        err = unpack_bool(io, &u);
-        if(err) goto exit;
-        val = (u ? OTRUE : OFALSE);
-        break;
-    case T_ATOM:
-        err = unpack_string(io, &y);
-        if(err) goto exit;
-        val = intern(string_string(y));
-        objfree(y);
-        break;
-    case T_STRING:
-        err = unpack_string(io, &val);
-        break;
-    case T_UINT:
-        err = unpack_uint(io, &u);
-        if(err) goto exit;
-        val = OBJI(type, u);
-        break;
-    default:
-        err = -EINVAL;
-        IOStream_print(iostderr, "%s> invalid type %d\n", __FUNCTION__, type);
-        break;
-    }
-  exit:
-    *x = (err ? ONONE : val);
-    return err;
-}
diff --git a/tools/lib/xdr.h b/tools/lib/xdr.h
deleted file mode 100644 (file)
index cb7d97d..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* $Id: xdr.h,v 1.2 2003/09/29 13:40:00 mjw Exp $ */
-#ifndef _SP_XDR_H_
-#define _SP_XDR_H_
-#include "iostream.h"
-#include "sxpr.h"
-int pack_uint(IOStream *out, unsigned int x);
-int unpack_uint(IOStream *in, unsigned int *x);
-int pack_string(IOStream *out, Sxpr x);
-int unpack_string(IOStream *in, Sxpr *x);
-int pack_cons(IOStream *out, Sxpr x);
-int unpack_cons(IOStream *in, Sxpr *x);
-int pack_sxpr(IOStream *out, Sxpr x);
-int unpack_sxpr(IOStream *in, Sxpr *x);
-#endif /* _SP_XDR_H_ */
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
new file mode 100644 (file)
index 0000000..8db55c2
--- /dev/null
@@ -0,0 +1,115 @@
+
+MAJOR    = 1.3
+MINOR    = 0
+SONAME   = libxc.so.$(MAJOR)
+
+CC       = gcc
+
+XEN_ROOT = ../..
+include $(XEN_ROOT)/tools/Make.defs
+
+vpath %.h      $(XEN_HYPERVISOR_IFS)
+INCLUDES += -I $(XEN_HYPERVISOR_IFS)
+
+vpath %h       $(XEN_LINUX_INCLUDE)
+INCLUDES += -I $(XEN_LINUX_INCLUDE)
+
+vpath %.h      $(XEN_XU)
+INCLUDES += -I $(XEN_XU)
+
+vpath %c       $(XEN_LIBXUTIL)
+INCLUDES += -I $(XEN_LIBXUTIL)
+
+LIB_SRCS :=
+LIB_SRCS += allocate.c
+#LIB_SRCS += enum.c
+LIB_SRCS += file_stream.c
+LIB_SRCS += gzip_stream.c
+#LIB_SRCS += hash_table.c
+LIB_SRCS += iostream.c
+#LIB_SRCS += kernel_stream.c
+#LIB_SRCS += lexis.c
+#LIB_SRCS += lzi_stream.c
+#LIB_SRCS += lzo_stream.c
+#LIB_SRCS += marshal.c
+#LIB_SRCS += socket_stream.c
+#LIB_SRCS += string_stream.c
+#LIB_SRCS += sxpr.c
+#LIB_SRCS += sxpr_parser.c
+LIB_SRCS += sys_net.c
+LIB_SRCS += sys_string.c
+#LIB_SRCS += xdr.c
+
+SRCS     :=
+SRCS     += xc_atropos.c
+SRCS     += xc_bvtsched.c
+SRCS     += xc_domain.c
+SRCS     += xc_evtchn.c
+SRCS     += xc_io.c
+SRCS     += xc_linux_build.c
+SRCS     += xc_linux_restore.c
+SRCS     += xc_linux_save.c
+SRCS     += xc_misc.c
+SRCS     += xc_netbsd_build.c
+SRCS     += xc_physdev.c
+SRCS     += xc_private.c
+SRCS     += xc_rrobin.c
+
+#SRCS     += $(LIB_SRCS)
+
+CFLAGS   += -Wall
+CFLAGS   += -Werror
+CFLAGS   += -g
+CFLAGS   += -O3
+CFLAGS   += -fno-strict-aliasing
+CFLAGS   += $(INCLUDES)
+# Get gcc to generate the dependencies for us.
+CFLAGS   += -Wp,-MD,.$(@F).d
+DEPS     = .*.d
+
+OBJS     = $(patsubst %.c,%.o,$(SRCS))
+
+LIB      = libxc.so libxc.so.$(MAJOR) libxc.so.$(MAJOR).$(MINOR)
+
+all: check-for-zlib $(LIB)
+
+check-for-zlib:
+       @if [ ! -e /usr/include/zlib.h ]; then \
+       echo "***********************************************************"; \
+       echo "ERROR: install zlib header files (http://www.gzip.org/zlib)"; \
+       echo "***********************************************************"; \
+       false; \
+       fi
+
+install: all
+       mkdir -p $(prefix)/usr/lib
+       mkdir -p $(prefix)/usr/include
+       install -m0755 $(LIB) $(prefix)/usr/lib
+       install -m0644 xc.h $(prefix)/usr/include
+
+clean:
+       $(RM) *.a *.so *.o *.rpm $(LIB)
+       $(RM) *~
+       $(RM) $(DEPS)
+
+rpm: all
+       rm -rf staging
+       mkdir staging
+       mkdir staging/i386
+       rpmbuild --define "staging$$PWD/staging" --define '_builddir.' \
+               --define "_rpmdir$$PWD/staging" -bb rpm.spec
+       mv staging/i386/*.rpm .
+       rm -rf staging
+
+libxc.so:
+       ln -sf libxc.so.$(MAJOR) $@
+libxc.so.$(MAJOR):
+       ln -sf libxc.so.$(MAJOR).$(MINOR) $@
+libxc.so.$(MAJOR).$(MINOR): $(OBJS)
+       $(CC) -Wl,-soname -Wl,$(SONAME) -shared -o $@ $^ ../libxutil/libxutil.a -lz 
+
+%.o: %.c Makefile
+
+#      $(CC) $(CFLAGS) -o $@ $<
+
+-include $(DEPS)
diff --git a/tools/libxc/rpm.spec b/tools/libxc/rpm.spec
new file mode 100644 (file)
index 0000000..1b4c5fc
--- /dev/null
@@ -0,0 +1,28 @@
+Summary: Xen control interface library
+Name: xen-internal-library
+Version: 1.2
+Release: 1
+License: Xen
+Group: Xen
+BuildRoot: %{staging}
+%description
+Library to make it easier to access the Xen control interfaces.
+
+%pre
+%preun
+%install
+install -m 0755 -d $RPM_BUILD_ROOT/lib
+install -m 0755 libxc.a $RPM_BUILD_ROOT/lib/libxc.a
+install -m 0755 libxc.so $RPM_BUILD_ROOT/lib/libxc.so
+install -m 0755 -d $RPM_BUILD_ROOT/include
+install -m 0644 xc.h $RPM_BUILD_ROOT/include/xc.h
+%clean
+%post
+%postun
+%files
+%defattr(-,root,root)
+%dir /lib
+/lib/libxc.a
+/lib/libxc.so
+%dir /include
+/include/xc.h
diff --git a/tools/libxc/xc.h b/tools/libxc/xc.h
new file mode 100644 (file)
index 0000000..f969260
--- /dev/null
@@ -0,0 +1,203 @@
+/******************************************************************************
+ * xc.h
+ * 
+ * A library for low-level access to the Xen control interfaces.
+ * 
+ * Copyright (c) 2003, K A Fraser.
+ */
+
+#ifndef __XC_H__
+#define __XC_H__
+
+typedef unsigned char      u8;
+typedef unsigned short     u16;
+typedef unsigned long      u32;
+typedef unsigned long long u64;
+typedef signed char        s8;
+typedef signed short       s16;
+typedef signed long        s32;
+typedef signed long long   s64;
+
+/* Obtain or relinquish a handle on the 'xc' library. */
+int xc_interface_open(void);
+int xc_interface_close(int xc_handle);
+
+typedef struct {
+    u32           domid;
+    unsigned int  cpu;
+    unsigned int  dying:1, crashed:1, shutdown:1, 
+                  paused:1, blocked:1, running:1;
+    unsigned int  shutdown_reason; /* only meaningful if shutdown==1 */
+    unsigned long nr_pages;
+    unsigned long shared_info_frame;
+    u64           cpu_time;
+#define XC_DOMINFO_MAXNAME 16
+    char          name[XC_DOMINFO_MAXNAME];
+    unsigned long max_memkb;
+} xc_dominfo_t;
+
+typedef struct xc_shadow_control_stats_st
+{
+    unsigned long fault_count;
+    unsigned long dirty_count;
+    unsigned long dirty_net_count;     
+    unsigned long dirty_block_count;     
+} xc_shadow_control_stats_t;
+
+int xc_domain_create(int xc_handle, 
+                     unsigned int mem_kb, 
+                     const char *name,
+                     int cpu,
+                     u32 *pdomid);
+int xc_domain_pause(int xc_handle, 
+                    u32 domid);
+int xc_domain_unpause(int xc_handle, 
+                      u32 domid);
+int xc_domain_destroy(int xc_handle, 
+                      u32 domid);
+int xc_domain_pincpu(int xc_handle,
+                     u32 domid,
+                     int cpu);
+int xc_domain_getinfo(int xc_handle,
+                      u32 first_domid, 
+                      unsigned int max_doms,
+                      xc_dominfo_t *info);
+
+int xc_shadow_control(int xc_handle,
+                      u32 domid, 
+                      unsigned int sop,
+                      unsigned long *dirty_bitmap,
+                      unsigned long pages,
+                      xc_shadow_control_stats_t *stats);
+
+
+#define XCFLAGS_VERBOSE 1
+#define XCFLAGS_LIVE    2
+#define XCFLAGS_DEBUG   4
+
+struct XcIOContext;
+int xc_linux_save(int xc_handle, struct XcIOContext *ioctxt);
+int xc_linux_restore(int xc_handle, struct XcIOContext *ioctxt);
+
+int xc_linux_build(int xc_handle,
+                   u32 domid,
+                   const char *image_name,
+                   const char *ramdisk_name,
+                   const char *cmdline,
+                   unsigned int control_evtchn,
+                   unsigned long flags);
+
+int xc_netbsd_build(int xc_handle,
+                    u32 domid,
+                    const char *image_name,
+                    const char *cmdline,
+                    unsigned int control_evtchn);
+
+int xc_bvtsched_global_set(int xc_handle,
+                           unsigned long ctx_allow);
+
+int xc_bvtsched_domain_set(int xc_handle,
+                           u32 domid,
+                           unsigned long mcuadv,
+                           unsigned long warp,
+                           unsigned long warpl,
+                           unsigned long warpu);
+
+int xc_bvtsched_global_get(int xc_handle,
+                           unsigned long *ctx_allow);
+
+int xc_bvtsched_domain_get(int xc_handle,
+                           u32 domid,
+                           unsigned long *mcuadv,
+                           unsigned long *warp,
+                           unsigned long *warpl,
+                           unsigned long *warpu);
+
+int xc_atropos_domain_set(int xc_handle,
+                          u32 domid,
+                          u64 period, u64 slice, u64 latency,
+                          int xtratime);
+
+int xc_atropos_domain_get(int xc_handle,
+                          u32 domid,
+                          u64* period, u64 *slice, u64 *latency,
+                          int *xtratime);
+
+int xc_rrobin_global_set(int xc_handle, u64 slice);
+
+int xc_rrobin_global_get(int xc_handle, u64 *slice);
+
+#define DOMID_SELF              (0x7FFFFFFEU)
+
+typedef struct {
+#define EVTCHNSTAT_closed       0  /* Chennel is not in use.                 */
+#define EVTCHNSTAT_unbound      1  /* Channel is not bound to a source.      */
+#define EVTCHNSTAT_interdomain  2  /* Channel is connected to remote domain. */
+#define EVTCHNSTAT_pirq         3  /* Channel is bound to a phys IRQ line.   */
+#define EVTCHNSTAT_virq         4  /* Channel is bound to a virtual IRQ line */
+    int status;
+    union {
+        struct {
+            u32 dom;
+            int port;
+        } interdomain;
+        int pirq;
+        int virq;
+    } u;
+} xc_evtchn_status_t;
+
+int xc_evtchn_bind_interdomain(int xc_handle,
+                               u32 dom1,   /* may be DOMID_SELF */
+                               u32 dom2,   /* may be DOMID_SELF */
+                               int *port1,
+                               int *port2);
+int xc_evtchn_bind_virq(int xc_handle,
+                        int virq,
+                        int *port);
+int xc_evtchn_close(int xc_handle,
+                    u32 dom,   /* may be DOMID_SELF */
+                    int port);
+int xc_evtchn_send(int xc_handle,
+                   int local_port);
+int xc_evtchn_status(int xc_handle,
+                     u32 dom, /* may be DOMID_SELF */
+                     int port,
+                     xc_evtchn_status_t *status);
+
+int xc_physdev_pci_access_modify(int xc_handle,
+                                 u32 domid,
+                                 int bus,
+                                 int dev,
+                                 int func,
+                                 int enable);
+
+int xc_readconsolering(int xc_handle,
+                       char *str, 
+                       unsigned int max_chars, 
+                       int clear);
+
+typedef struct {
+    int ht_per_core;
+    int cores;
+    unsigned long total_pages;
+    unsigned long free_pages;
+    unsigned long cpu_khz;
+} xc_physinfo_t;
+
+int xc_physinfo(int xc_handle,
+                xc_physinfo_t *info);
+
+int xc_domain_setname(int xc_handle,
+                      u32 domid, 
+                      char *name);
+
+int xc_domain_setinitialmem(int xc_handle,
+                            u32 domid, 
+                            unsigned int initial_memkb);
+
+int xc_domain_setmaxmem(int xc_handle,
+                            u32 domid, 
+                            unsigned int max_memkb);
+
+
+#endif /* __XC_H__ */
diff --git a/tools/libxc/xc_atropos.c b/tools/libxc/xc_atropos.c
new file mode 100644 (file)
index 0000000..13d07ca
--- /dev/null
@@ -0,0 +1,51 @@
+/******************************************************************************
+ * xc_atropos.c
+ * 
+ * API for manipulating parameters of the Atropos scheduler.
+ * 
+ * by Mark Williamson, Copyright (c) 2004 Intel Research Cambridge.
+ */
+
+#include "xc_private.h"
+
+int xc_atropos_domain_set(int xc_handle,
+                          u32 domid, u64 period, u64 slice, u64 latency,
+                          int xtratime)
+{
+    dom0_op_t op;
+    struct atropos_adjdom *p = &op.u.adjustdom.u.atropos;
+
+    op.cmd = DOM0_ADJUSTDOM;
+    op.u.adjustdom.domain  = (domid_t)domid;
+    op.u.adjustdom.sched_id = SCHED_ATROPOS;
+    op.u.adjustdom.direction = SCHED_INFO_PUT;
+
+    p->nat_period   = period;
+    p->nat_slice    = slice;
+    p->latency  = latency;
+    p->xtratime = xtratime;
+
+    return do_dom0_op(xc_handle, &op);
+}
+
+int xc_atropos_domain_get(int xc_handle, u32 domid, u64 *period,
+                          u64 *slice, u64 *latency, int *xtratime)
+{
+    dom0_op_t op;
+    int ret;
+    struct atropos_adjdom *p = &op.u.adjustdom.u.atropos;
+
+    op.cmd = DOM0_ADJUSTDOM;    
+    op.u.adjustdom.domain = (domid_t)domid;
+    op.u.adjustdom.sched_id = SCHED_ATROPOS;
+    op.u.adjustdom.direction = SCHED_INFO_GET;
+
+    ret = do_dom0_op(xc_handle, &op);
+
+    *period   = p->nat_period;
+    *slice    = p->nat_slice;
+    *latency  = p->latency;
+    *xtratime = p->xtratime;
+
+    return ret;
+}
diff --git a/tools/libxc/xc_bvtsched.c b/tools/libxc/xc_bvtsched.c
new file mode 100644 (file)
index 0000000..aeaddcf
--- /dev/null
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * xc_bvtsched.c
+ * 
+ * API for manipulating parameters of the Borrowed Virtual Time scheduler.
+ * 
+ * Copyright (c) 2003, K A Fraser.
+ */
+
+#include "xc_private.h"
+
+int xc_bvtsched_global_set(int xc_handle,
+                           unsigned long ctx_allow)
+{
+    dom0_op_t op;
+
+    op.cmd = DOM0_SCHEDCTL;
+    op.u.schedctl.sched_id = SCHED_BVT;
+    op.u.schedctl.direction = SCHED_INFO_PUT;
+    op.u.schedctl.u.bvt.ctx_allow = ctx_allow;
+
+    return do_dom0_op(xc_handle, &op);
+}
+
+int xc_bvtsched_global_get(int xc_handle,
+                           unsigned long *ctx_allow)
+{
+    dom0_op_t op;
+    int ret;
+    
+    op.cmd = DOM0_SCHEDCTL;
+    op.u.schedctl.sched_id = SCHED_BVT;
+    op.u.schedctl.direction = SCHED_INFO_GET;
+
+    ret = do_dom0_op(xc_handle, &op);
+
+    *ctx_allow = op.u.schedctl.u.bvt.ctx_allow;
+
+    return ret;
+}
+
+int xc_bvtsched_domain_set(int xc_handle,
+                           u32 domid,
+                           unsigned long mcuadv,
+                           unsigned long warp,
+                           unsigned long warpl,
+                           unsigned long warpu)
+{
+    dom0_op_t op;
+    struct bvt_adjdom *bvtadj = &op.u.adjustdom.u.bvt;
+
+    op.cmd = DOM0_ADJUSTDOM;
+    op.u.adjustdom.domain  = (domid_t)domid;
+    op.u.adjustdom.sched_id = SCHED_BVT;
+    op.u.adjustdom.direction = SCHED_INFO_PUT;
+
+    bvtadj->mcu_adv = mcuadv;
+    bvtadj->warp    = warp;
+    bvtadj->warpl   = warpl;
+    bvtadj->warpu   = warpu;
+    return do_dom0_op(xc_handle, &op);
+}
+
+
+int xc_bvtsched_domain_get(int xc_handle,
+                           u32 domid,
+                           unsigned long *mcuadv,
+                           unsigned long *warp,
+                           unsigned long *warpl,
+                           unsigned long *warpu)
+{
+    
+    dom0_op_t op;
+    int ret;
+    struct bvt_adjdom *adjptr = &op.u.adjustdom.u.bvt;
+
+    op.cmd = DOM0_ADJUSTDOM;
+    op.u.adjustdom.domain  = (domid_t)domid;
+    op.u.adjustdom.sched_id = SCHED_BVT;
+    op.u.adjustdom.direction = SCHED_INFO_GET;
+
+    ret = do_dom0_op(xc_handle, &op);
+
+    *mcuadv = adjptr->mcu_adv;
+    *warp   = adjptr->warp;
+    *warpl  = adjptr->warpl;
+    *warpu  = adjptr->warpu;
+    return ret;
+}
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
new file mode 100644 (file)
index 0000000..ab83d0c
--- /dev/null
@@ -0,0 +1,194 @@
+/******************************************************************************
+ * xc_domain.c
+ * 
+ * API for manipulating and obtaining information on domains.
+ * 
+ * Copyright (c) 2003, K A Fraser.
+ */
+
+#include "xc_private.h"
+
+int xc_domain_create(int xc_handle,
+                     unsigned int mem_kb, 
+                     const char *name,
+                     int cpu,
+                     u32 *pdomid)
+{
+    int err;
+    dom0_op_t op;
+
+    op.cmd = DOM0_CREATEDOMAIN;
+    op.u.createdomain.memory_kb = mem_kb;
+    strncpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
+    op.u.createdomain.name[MAX_DOMAIN_NAME-1] = '\0';
+    op.u.createdomain.cpu = cpu;
+
+    if ( (err = do_dom0_op(xc_handle, &op)) == 0 )
+        *pdomid = (u32)op.u.createdomain.domain;
+
+    return err;
+}    
+
+
+int xc_domain_pause(int xc_handle, 
+                    u32 domid)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_PAUSEDOMAIN;
+    op.u.pausedomain.domain = (domid_t)domid;
+    return do_dom0_op(xc_handle, &op);
+}    
+
+
+int xc_domain_unpause(int xc_handle,
+                      u32 domid)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_UNPAUSEDOMAIN;
+    op.u.unpausedomain.domain = (domid_t)domid;
+    return do_dom0_op(xc_handle, &op);
+}    
+
+
+int xc_domain_destroy(int xc_handle,
+                      u32 domid)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_DESTROYDOMAIN;
+    op.u.destroydomain.domain = (domid_t)domid;
+    return do_dom0_op(xc_handle, &op);
+}
+
+int xc_domain_pincpu(int xc_handle,
+                     u32 domid, 
+                     int cpu)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_PINCPUDOMAIN;
+    op.u.pincpudomain.domain = (domid_t)domid;
+    op.u.pincpudomain.cpu  = cpu;
+    return do_dom0_op(xc_handle, &op);
+}
+
+
+int xc_domain_getinfo(int xc_handle,
+                      u32 first_domid,
+                      unsigned int max_doms,
+                      xc_dominfo_t *info)
+{
+    unsigned int nr_doms;
+    u32 next_domid = first_domid;
+    dom0_op_t op;
+
+    for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
+    {
+        op.cmd = DOM0_GETDOMAININFO;
+        op.u.getdomaininfo.domain = (domid_t)next_domid;
+        op.u.getdomaininfo.ctxt = NULL; /* no exec context info, thanks. */
+        if ( do_dom0_op(xc_handle, &op) < 0 )
+            break;
+        info->domid   = (u32)op.u.getdomaininfo.domain;
+
+        info->cpu     =
+            (op.u.getdomaininfo.flags>>DOMFLAGS_CPUSHIFT) & DOMFLAGS_CPUMASK;
+
+        info->dying    = !!(op.u.getdomaininfo.flags & DOMFLAGS_DYING);
+        info->crashed  = !!(op.u.getdomaininfo.flags & DOMFLAGS_CRASHED);
+        info->shutdown = !!(op.u.getdomaininfo.flags & DOMFLAGS_SHUTDOWN);
+        info->paused   = !!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED);
+        info->blocked  = !!(op.u.getdomaininfo.flags & DOMFLAGS_BLOCKED);
+        info->running  = !!(op.u.getdomaininfo.flags & DOMFLAGS_RUNNING);
+
+        info->shutdown_reason = 
+            (op.u.getdomaininfo.flags>>DOMFLAGS_SHUTDOWNSHIFT) & 
+            DOMFLAGS_SHUTDOWNMASK;
+
+        info->nr_pages = op.u.getdomaininfo.tot_pages;
+        info->max_memkb = op.u.getdomaininfo.max_pages<<(PAGE_SHIFT-10);
+        info->shared_info_frame = op.u.getdomaininfo.shared_info_frame;
+        info->cpu_time = op.u.getdomaininfo.cpu_time;
+        strncpy(info->name, op.u.getdomaininfo.name, XC_DOMINFO_MAXNAME);
+        info->name[XC_DOMINFO_MAXNAME-1] = '\0';
+
+        next_domid = (u32)op.u.getdomaininfo.domain + 1;
+        info++;
+    }
+
+    return nr_doms;
+}
+
+int xc_domain_getfullinfo(int xc_handle,
+                          u32 domid,
+                          dom0_op_t *op,
+                          full_execution_context_t *ctxt )
+{
+    int rc;
+    op->cmd = DOM0_GETDOMAININFO;
+    op->u.getdomaininfo.domain = (domid_t)domid;
+    op->u.getdomaininfo.ctxt = ctxt;
+
+    rc = do_dom0_op(xc_handle, op);
+    if ( ((u32)op->u.getdomaininfo.domain != domid) && rc > 0 )
+        return -ESRCH;
+    else
+        return rc;
+}
+
+
+int xc_shadow_control(int xc_handle,
+                      u32 domid, 
+                      unsigned int sop,
+                      unsigned long *dirty_bitmap,
+                      unsigned long pages,
+                      xc_shadow_control_stats_t *stats )
+{
+    int rc;
+    dom0_op_t op;
+    op.cmd = DOM0_SHADOW_CONTROL;
+    op.u.shadow_control.domain = (domid_t)domid;
+    op.u.shadow_control.op     = sop;
+    op.u.shadow_control.dirty_bitmap = dirty_bitmap;
+    op.u.shadow_control.pages  = pages;
+
+    rc = do_dom0_op(xc_handle, &op);
+
+    if ( stats )
+        memcpy(stats, &op.u.shadow_control.stats,
+               sizeof(xc_shadow_control_stats_t));
+
+    return (rc == 0) ? op.u.shadow_control.pages : rc;
+}
+
+int xc_domain_setname(int xc_handle,
+                      u32 domid, 
+                      char *name)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_SETDOMAINNAME;
+    op.u.setdomainname.domain = (domid_t)domid;
+    strncpy(op.u.setdomainname.name, name, MAX_DOMAIN_NAME);
+    return do_dom0_op(xc_handle, &op);
+}
+
+int xc_domain_setinitialmem(int xc_handle,
+                            u32 domid, 
+                            unsigned int initial_memkb)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_SETDOMAININITIALMEM;
+    op.u.setdomaininitialmem.domain = (domid_t)domid;
+    op.u.setdomaininitialmem.initial_memkb = initial_memkb;
+    return do_dom0_op(xc_handle, &op);
+}
+
+int xc_domain_setmaxmem(int xc_handle,
+                        u32 domid, 
+                        unsigned int max_memkb)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_SETDOMAINMAXMEM;
+    op.u.setdomainmaxmem.domain = (domid_t)domid;
+    op.u.setdomainmaxmem.max_memkb = max_memkb;
+    return do_dom0_op(xc_handle, &op);
+}
+
diff --git a/tools/libxc/xc_elf.h b/tools/libxc/xc_elf.h
new file mode 100644 (file)
index 0000000..e0d0c26
--- /dev/null
@@ -0,0 +1,523 @@
+/*
+ * Copyright (c) 1995, 1996 Erik Theisen.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+typedef u_int8_t       Elf_Byte;
+
+typedef u_int32_t      Elf32_Addr;     /* Unsigned program address */
+typedef u_int32_t      Elf32_Off;      /* Unsigned file offset */
+typedef int32_t                Elf32_Sword;    /* Signed large integer */
+typedef u_int32_t      Elf32_Word;     /* Unsigned large integer */
+typedef u_int16_t      Elf32_Half;     /* Unsigned medium integer */
+
+typedef u_int64_t      Elf64_Addr;
+typedef u_int64_t      Elf64_Off;
+typedef int32_t                Elf64_Shalf;
+
+typedef int32_t                Elf64_Sword;
+typedef u_int32_t      Elf64_Word;
+
+typedef int64_t                Elf64_Sxword;
+typedef u_int64_t      Elf64_Xword;
+
+typedef u_int32_t      Elf64_Half;
+typedef u_int16_t      Elf64_Quarter;
+
+/*
+ * e_ident[] identification indexes 
+ * See http://www.caldera.com/developers/gabi/2000-07-17/ch4.eheader.html
+ */
+#define EI_MAG0                0               /* file ID */
+#define EI_MAG1                1               /* file ID */
+#define EI_MAG2                2               /* file ID */
+#define EI_MAG3                3               /* file ID */
+#define EI_CLASS       4               /* file class */
+#define EI_DATA                5               /* data encoding */
+#define EI_VERSION     6               /* ELF header version */
+#define EI_OSABI       7               /* OS/ABI ID */
+#define EI_ABIVERSION  8               /* ABI version */ 
+#define EI_PAD         9               /* start of pad bytes */
+#define EI_NIDENT      16              /* Size of e_ident[] */
+
+/* e_ident[] magic number */
+#define        ELFMAG0         0x7f            /* e_ident[EI_MAG0] */
+#define        ELFMAG1         'E'             /* e_ident[EI_MAG1] */
+#define        ELFMAG2         'L'             /* e_ident[EI_MAG2] */
+#define        ELFMAG3         'F'             /* e_ident[EI_MAG3] */
+#define        ELFMAG          "\177ELF"       /* magic */
+#define        SELFMAG         4               /* size of magic */
+
+/* e_ident[] file class */
+#define        ELFCLASSNONE    0               /* invalid */
+#define        ELFCLASS32      1               /* 32-bit objs */
+#define        ELFCLASS64      2               /* 64-bit objs */
+#define        ELFCLASSNUM     3               /* number of classes */
+
+/* e_ident[] data encoding */
+#define ELFDATANONE    0               /* invalid */
+#define ELFDATA2LSB    1               /* Little-Endian */
+#define ELFDATA2MSB    2               /* Big-Endian */
+#define ELFDATANUM     3               /* number of data encode defines */
+
+/* e_ident[] Operating System/ABI */
+#define ELFOSABI_SYSV          0       /* UNIX System V ABI */
+#define ELFOSABI_HPUX          1       /* HP-UX operating system */
+#define ELFOSABI_NETBSD                2       /* NetBSD */
+#define ELFOSABI_LINUX         3       /* GNU/Linux */
+#define ELFOSABI_HURD          4       /* GNU/Hurd */
+#define ELFOSABI_86OPEN                5       /* 86Open common IA32 ABI */
+#define ELFOSABI_SOLARIS       6       /* Solaris */
+#define ELFOSABI_MONTEREY      7       /* Monterey */
+#define ELFOSABI_IRIX          8       /* IRIX */
+#define ELFOSABI_FREEBSD       9       /* FreeBSD */
+#define ELFOSABI_TRU64         10      /* TRU64 UNIX */
+#define ELFOSABI_MODESTO       11      /* Novell Modesto */
+#define ELFOSABI_OPENBSD       12      /* OpenBSD */
+#define ELFOSABI_ARM           97      /* ARM */
+#define ELFOSABI_STANDALONE    255     /* Standalone (embedded) application */
+
+/* e_ident */
+#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
+                      (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
+                      (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
+                      (ehdr).e_ident[EI_MAG3] == ELFMAG3)
+
+/* ELF Header */
+typedef struct elfhdr {
+       unsigned char   e_ident[EI_NIDENT]; /* ELF Identification */
+       Elf32_Half      e_type;         /* object file type */
+       Elf32_Half      e_machine;      /* machine */
+       Elf32_Word      e_version;      /* object file version */
+       Elf32_Addr      e_entry;        /* virtual entry point */
+       Elf32_Off       e_phoff;        /* program header table offset */
+       Elf32_Off       e_shoff;        /* section header table offset */
+       Elf32_Word      e_flags;        /* processor-specific flags */
+       Elf32_Half      e_ehsize;       /* ELF header size */
+       Elf32_Half      e_phentsize;    /* program header entry size */
+       Elf32_Half      e_phnum;        /* number of program header entries */
+       Elf32_Half      e_shentsize;    /* section header entry size */
+       Elf32_Half      e_shnum;        /* number of section header entries */
+       Elf32_Half      e_shstrndx;     /* section header table's "section 
+                                          header string table" entry offset */
+} Elf32_Ehdr;
+
+typedef struct {
+       unsigned char   e_ident[EI_NIDENT];     /* Id bytes */
+       Elf64_Quarter   e_type;                 /* file type */
+       Elf64_Quarter   e_machine;              /* machine type */
+       Elf64_Half      e_version;              /* version number */
+       Elf64_Addr      e_entry;                /* entry point */
+       Elf64_Off       e_phoff;                /* Program hdr offset */
+       Elf64_Off       e_shoff;                /* Section hdr offset */
+       Elf64_Half      e_flags;                /* Processor flags */
+       Elf64_Quarter   e_ehsize;               /* sizeof ehdr */
+       Elf64_Quarter   e_phentsize;            /* Program header entry size */
+       Elf64_Quarter   e_phnum;                /* Number of program headers */
+       Elf64_Quarter   e_shentsize;            /* Section header entry size */
+       Elf64_Quarter   e_shnum;                /* Number of section headers */
+       Elf64_Quarter   e_shstrndx;             /* String table index */
+} Elf64_Ehdr;
+
+/* e_type */
+#define ET_NONE                0               /* No file type */
+#define ET_REL         1               /* relocatable file */
+#define ET_EXEC                2               /* executable file */
+#define ET_DYN         3               /* shared object file */
+#define ET_CORE                4               /* core file */
+#define ET_NUM         5               /* number of types */
+#define ET_LOPROC      0xff00          /* reserved range for processor */
+#define ET_HIPROC      0xffff          /*  specific e_type */
+
+/* e_machine */
+#define EM_NONE                0               /* No Machine */
+#define EM_M32         1               /* AT&T WE 32100 */
+#define EM_SPARC       2               /* SPARC */
+#define EM_386         3               /* Intel 80386 */
+#define EM_68K         4               /* Motorola 68000 */
+#define EM_88K         5               /* Motorola 88000 */
+#define EM_486         6               /* Intel 80486 - unused? */
+#define EM_860         7               /* Intel 80860 */
+#define EM_MIPS                8               /* MIPS R3000 Big-Endian only */
+/* 
+ * Don't know if EM_MIPS_RS4_BE,
+ * EM_SPARC64, EM_PARISC,
+ * or EM_PPC are ABI compliant
+ */
+#define EM_MIPS_RS4_BE 10              /* MIPS R4000 Big-Endian */
+#define EM_SPARC64     11              /* SPARC v9 64-bit unoffical */
+#define EM_PARISC      15              /* HPPA */
+#define EM_SPARC32PLUS 18              /* Enhanced instruction set SPARC */
+#define EM_PPC         20              /* PowerPC */
+#define EM_ARM         40              /* Advanced RISC Machines ARM */
+#define EM_ALPHA       41              /* DEC ALPHA */
+#define EM_SPARCV9     43              /* SPARC version 9 */
+#define EM_ALPHA_EXP   0x9026          /* DEC ALPHA */
+#define EM_X86_64      62              /* AMD x86-64 architecture */
+#define EM_VAX         75              /* DEC VAX */
+#define EM_NUM         15              /* number of machine types */
+
+/* Version */
+#define EV_NONE                0               /* Invalid */
+#define EV_CURRENT     1               /* Current */
+#define EV_NUM         2               /* number of versions */
+
+/* Section Header */
+typedef struct {
+       Elf32_Word      sh_name;        /* name - index into section header
+                                          string table section */
+       Elf32_Word      sh_type;        /* type */
+       Elf32_Word      sh_flags;       /* flags */
+       Elf32_Addr      sh_addr;        /* address */
+       Elf32_Off       sh_offset;      /* file offset */
+       Elf32_Word      sh_size;        /* section size */
+       Elf32_Word      sh_link;        /* section header table index link */
+       Elf32_Word      sh_info;        /* extra information */
+       Elf32_Word      sh_addralign;   /* address alignment */
+       Elf32_Word      sh_entsize;     /* section entry size */
+} Elf32_Shdr;
+
+typedef struct {
+       Elf64_Half      sh_name;        /* section name */
+       Elf64_Half      sh_type;        /* section type */
+       Elf64_Xword     sh_flags;       /* section flags */
+       Elf64_Addr      sh_addr;        /* virtual address */
+       Elf64_Off       sh_offset;      /* file offset */
+       Elf64_Xword     sh_size;        /* section size */
+       Elf64_Half      sh_link;        /* link to another */
+       Elf64_Half      sh_info;        /* misc info */
+       Elf64_Xword     sh_addralign;   /* memory alignment */
+       Elf64_Xword     sh_entsize;     /* table entry size */
+} Elf64_Shdr;
+
+/* Special Section Indexes */
+#define SHN_UNDEF      0               /* undefined */
+#define SHN_LORESERVE  0xff00          /* lower bounds of reserved indexes */
+#define SHN_LOPROC     0xff00          /* reserved range for processor */
+#define SHN_HIPROC     0xff1f          /*   specific section indexes */
+#define SHN_ABS                0xfff1          /* absolute value */
+#define SHN_COMMON     0xfff2          /* common symbol */
+#define SHN_HIRESERVE  0xffff          /* upper bounds of reserved indexes */
+
+/* sh_type */
+#define SHT_NULL       0               /* inactive */
+#define SHT_PROGBITS   1               /* program defined information */
+#define SHT_SYMTAB     2               /* symbol table section */
+#define SHT_STRTAB     3               /* string table section */
+#define SHT_RELA       4               /* relocation section with addends*/
+#define SHT_HASH       5               /* symbol hash table section */
+#define SHT_DYNAMIC    6               /* dynamic section */
+#define SHT_NOTE       7               /* note section */
+#define SHT_NOBITS     8               /* no space section */
+#define SHT_REL                9               /* relation section without addends */
+#define SHT_SHLIB      10              /* reserved - purpose unknown */
+#define SHT_DYNSYM     11              /* dynamic symbol table section */
+#define SHT_NUM                12              /* number of section types */
+#define SHT_LOPROC     0x70000000      /* reserved range for processor */
+#define SHT_HIPROC     0x7fffffff      /*  specific section header types */
+#define SHT_LOUSER     0x80000000      /* reserved range for application */
+#define SHT_HIUSER     0xffffffff      /*  specific indexes */
+
+/* Section names */
+#define ELF_BSS         ".bss"         /* uninitialized data */
+#define ELF_DATA        ".data"                /* initialized data */
+#define ELF_DEBUG       ".debug"       /* debug */
+#define ELF_DYNAMIC     ".dynamic"     /* dynamic linking information */
+#define ELF_DYNSTR      ".dynstr"      /* dynamic string table */
+#define ELF_DYNSYM      ".dynsym"      /* dynamic symbol table */
+#define ELF_FINI        ".fini"                /* termination code */
+#define ELF_GOT         ".got"         /* global offset table */
+#define ELF_HASH        ".hash"                /* symbol hash table */
+#define ELF_INIT        ".init"                /* initialization code */
+#define ELF_REL_DATA    ".rel.data"    /* relocation data */
+#define ELF_REL_FINI    ".rel.fini"    /* relocation termination code */
+#define ELF_REL_INIT    ".rel.init"    /* relocation initialization code */
+#define ELF_REL_DYN     ".rel.dyn"     /* relocaltion dynamic link info */
+#define ELF_REL_RODATA  ".rel.rodata"  /* relocation read-only data */
+#define ELF_REL_TEXT    ".rel.text"    /* relocation code */
+#define ELF_RODATA      ".rodata"      /* read-only data */
+#define ELF_SHSTRTAB    ".shstrtab"    /* section header string table */
+#define ELF_STRTAB      ".strtab"      /* string table */
+#define ELF_SYMTAB      ".symtab"      /* symbol table */
+#define ELF_TEXT        ".text"                /* code */
+
+
+/* Section Attribute Flags - sh_flags */
+#define SHF_WRITE      0x1             /* Writable */
+#define SHF_ALLOC      0x2             /* occupies memory */
+#define SHF_EXECINSTR  0x4             /* executable */
+#define SHF_MASKPROC   0xf0000000      /* reserved bits for processor */
+                                       /*  specific section attributes */
+
+/* Symbol Table Entry */
+typedef struct elf32_sym {
+       Elf32_Word      st_name;        /* name - index into string table */
+       Elf32_Addr      st_value;       /* symbol value */
+       Elf32_Word      st_size;        /* symbol size */
+       unsigned char   st_info;        /* type and binding */
+       unsigned char   st_other;       /* 0 - no defined meaning */
+       Elf32_Half      st_shndx;       /* section header index */
+} Elf32_Sym;
+
+typedef struct {
+       Elf64_Half      st_name;        /* Symbol name index in str table */
+       Elf_Byte        st_info;        /* type / binding attrs */
+       Elf_Byte        st_other;       /* unused */
+       Elf64_Quarter   st_shndx;       /* section index of symbol */
+       Elf64_Xword     st_value;       /* value of symbol */
+       Elf64_Xword     st_size;        /* size of symbol */
+} Elf64_Sym;
+
+/* Symbol table index */
+#define STN_UNDEF      0               /* undefined */
+
+/* Extract symbol info - st_info */
+#define ELF32_ST_BIND(x)       ((x) >> 4)
+#define ELF32_ST_TYPE(x)       (((unsigned int) x) & 0xf)
+#define ELF32_ST_INFO(b,t)     (((b) << 4) + ((t) & 0xf))
+
+#define ELF64_ST_BIND(x)       ((x) >> 4)
+#define ELF64_ST_TYPE(x)       (((unsigned int) x) & 0xf)
+#define ELF64_ST_INFO(b,t)     (((b) << 4) + ((t) & 0xf))
+
+/* Symbol Binding - ELF32_ST_BIND - st_info */
+#define STB_LOCAL      0               /* Local symbol */
+#define STB_GLOBAL     1               /* Global symbol */
+#define STB_WEAK       2               /* like global - lower precedence */
+#define STB_NUM                3               /* number of symbol bindings */
+#define STB_LOPROC     13              /* reserved range for processor */
+#define STB_HIPROC     15              /*  specific symbol bindings */
+
+/* Symbol type - ELF32_ST_TYPE - st_info */
+#define STT_NOTYPE     0               /* not specified */
+#define STT_OBJECT     1               /* data object */
+#define STT_FUNC       2               /* function */
+#define STT_SECTION    3               /* section */
+#define STT_FILE       4               /* file */
+#define STT_NUM                5               /* number of symbol types */
+#define STT_LOPROC     13              /* reserved range for processor */
+#define STT_HIPROC     15              /*  specific symbol types */
+
+/* Relocation entry with implicit addend */
+typedef struct {
+       Elf32_Addr      r_offset;       /* offset of relocation */
+       Elf32_Word      r_info;         /* symbol table index and type */
+} Elf32_Rel;
+
+/* Relocation entry with explicit addend */
+typedef struct {
+       Elf32_Addr      r_offset;       /* offset of relocation */
+       Elf32_Word      r_info;         /* symbol table index and type */
+       Elf32_Sword     r_addend;
+} Elf32_Rela;
+
+/* Extract relocation info - r_info */
+#define ELF32_R_SYM(i)         ((i) >> 8)
+#define ELF32_R_TYPE(i)                ((unsigned char) (i))
+#define ELF32_R_INFO(s,t)      (((s) << 8) + (unsigned char)(t))
+
+typedef struct {
+       Elf64_Xword     r_offset;       /* where to do it */
+       Elf64_Xword     r_info;         /* index & type of relocation */
+} Elf64_Rel;
+
+typedef struct {
+       Elf64_Xword     r_offset;       /* where to do it */
+       Elf64_Xword     r_info;         /* index & type of relocation */
+       Elf64_Sxword    r_addend;       /* adjustment value */
+} Elf64_Rela;
+
+#define        ELF64_R_SYM(info)       ((info) >> 32)
+#define        ELF64_R_TYPE(info)      ((info) & 0xFFFFFFFF)
+#define ELF64_R_INFO(s,t)      (((s) << 32) + (u_int32_t)(t))
+
+/* Program Header */
+typedef struct {
+       Elf32_Word      p_type;         /* segment type */
+       Elf32_Off       p_offset;       /* segment offset */
+       Elf32_Addr      p_vaddr;        /* virtual address of segment */
+       Elf32_Addr      p_paddr;        /* physical address - ignored? */
+       Elf32_Word      p_filesz;       /* number of bytes in file for seg. */
+       Elf32_Word      p_memsz;        /* number of bytes in mem. for seg. */
+       Elf32_Word      p_flags;        /* flags */
+       Elf32_Word      p_align;        /* memory alignment */
+} Elf32_Phdr;
+
+typedef struct {
+       Elf64_Half      p_type;         /* entry type */
+       Elf64_Half      p_flags;        /* flags */
+       Elf64_Off       p_offset;       /* offset */
+       Elf64_Addr      p_vaddr;        /* virtual address */
+       Elf64_Addr      p_paddr;        /* physical address */
+       Elf64_Xword     p_filesz;       /* file size */
+       Elf64_Xword     p_memsz;        /* memory size */
+       Elf64_Xword     p_align;        /* memory & file alignment */
+} Elf64_Phdr;
+
+/* Segment types - p_type */
+#define PT_NULL                0               /* unused */
+#define PT_LOAD                1               /* loadable segment */
+#define PT_DYNAMIC     2               /* dynamic linking section */
+#define PT_INTERP      3               /* the RTLD */
+#define PT_NOTE                4               /* auxiliary information */
+#define PT_SHLIB       5               /* reserved - purpose undefined */
+#define PT_PHDR                6               /* program header */
+#define PT_NUM         7               /* Number of segment types */
+#define PT_LOPROC      0x70000000      /* reserved range for processor */
+#define PT_HIPROC      0x7fffffff      /*  specific segment types */
+
+/* Segment flags - p_flags */
+#define PF_X           0x1             /* Executable */
+#define PF_W           0x2             /* Writable */
+#define PF_R           0x4             /* Readable */
+#define PF_MASKPROC    0xf0000000      /* reserved bits for processor */
+                                       /*  specific segment flags */
+
+/* Dynamic structure */
+typedef struct {
+       Elf32_Sword     d_tag;          /* controls meaning of d_val */
+       union {
+               Elf32_Word      d_val;  /* Multiple meanings - see d_tag */
+               Elf32_Addr      d_ptr;  /* program virtual address */
+       } d_un;
+} Elf32_Dyn;
+
+typedef struct {
+       Elf64_Xword     d_tag;          /* controls meaning of d_val */
+       union {
+               Elf64_Addr      d_ptr;
+               Elf64_Xword     d_val;
+       } d_un;
+} Elf64_Dyn;
+
+/* Dynamic Array Tags - d_tag */
+#define DT_NULL                0               /* marks end of _DYNAMIC array */
+#define DT_NEEDED      1               /* string table offset of needed lib */
+#define DT_PLTRELSZ    2               /* size of relocation entries in PLT */
+#define DT_PLTGOT      3               /* address PLT/GOT */
+#define DT_HASH                4               /* address of symbol hash table */
+#define DT_STRTAB      5               /* address of string table */
+#define DT_SYMTAB      6               /* address of symbol table */
+#define DT_RELA                7               /* address of relocation table */
+#define DT_RELASZ      8               /* size of relocation table */
+#define DT_RELAENT     9               /* size of relocation entry */
+#define DT_STRSZ       10              /* size of string table */
+#define DT_SYMENT      11              /* size of symbol table entry */
+#define DT_INIT                12              /* address of initialization func. */
+#define DT_FINI                13              /* address of termination function */
+#define DT_SONAME      14              /* string table offset of shared obj */
+#define DT_RPATH       15              /* string table offset of library
+                                          search path */
+#define DT_SYMBOLIC    16              /* start sym search in shared obj. */
+#define DT_REL         17              /* address of rel. tbl. w addends */
+#define DT_RELSZ       18              /* size of DT_REL relocation table */
+#define DT_RELENT      19              /* size of DT_REL relocation entry */
+#define DT_PLTREL      20              /* PLT referenced relocation entry */
+#define DT_DEBUG       21              /* bugger */
+#define DT_TEXTREL     22              /* Allow rel. mod. to unwritable seg */
+#define DT_JMPREL      23              /* add. of PLT's relocation entries */
+#define DT_BIND_NOW    24              /* Bind now regardless of env setting */
+#define DT_NUM         25              /* Number used. */
+#define DT_LOPROC      0x70000000      /* reserved range for processor */
+#define DT_HIPROC      0x7fffffff      /*  specific dynamic array tags */
+       
+/* Standard ELF hashing function */
+unsigned int elf_hash(const unsigned char *name);
+
+/*
+ * Note Definitions
+ */
+typedef struct {
+       Elf32_Word namesz;
+       Elf32_Word descsz;
+       Elf32_Word type;
+} Elf32_Note;
+
+typedef struct {
+       Elf64_Half namesz;
+       Elf64_Half descsz;
+       Elf64_Half type;
+} Elf64_Note;
+
+
+#if defined(ELFSIZE)
+#define CONCAT(x,y)    __CONCAT(x,y)
+#define ELFNAME(x)     CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
+#define ELFNAME2(x,y)  CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
+#define ELFNAMEEND(x)  CONCAT(x,CONCAT(_elf,ELFSIZE))
+#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
+#endif
+
+#if defined(ELFSIZE) && (ELFSIZE == 32)
+#define Elf_Ehdr       Elf32_Ehdr
+#define Elf_Phdr       Elf32_Phdr
+#define Elf_Shdr       Elf32_Shdr
+#define Elf_Sym                Elf32_Sym
+#define Elf_Rel                Elf32_Rel
+#define Elf_RelA       Elf32_Rela
+#define Elf_Dyn                Elf32_Dyn
+#define Elf_Word       Elf32_Word
+#define Elf_Sword      Elf32_Sword
+#define Elf_Addr       Elf32_Addr
+#define Elf_Off                Elf32_Off
+#define Elf_Nhdr       Elf32_Nhdr
+#define Elf_Note       Elf32_Note
+
+#define ELF_R_SYM      ELF32_R_SYM
+#define ELF_R_TYPE     ELF32_R_TYPE
+#define ELF_R_INFO     ELF32_R_INFO
+#define ELFCLASS       ELFCLASS32
+
+#define ELF_ST_BIND    ELF32_ST_BIND
+#define ELF_ST_TYPE    ELF32_ST_TYPE
+#define ELF_ST_INFO    ELF32_ST_INFO
+
+#define AuxInfo                Aux32Info
+#elif defined(ELFSIZE) && (ELFSIZE == 64)
+#define Elf_Ehdr       Elf64_Ehdr
+#define Elf_Phdr       Elf64_Phdr
+#define Elf_Shdr       Elf64_Shdr
+#define Elf_Sym                Elf64_Sym
+#define Elf_Rel                Elf64_Rel
+#define Elf_RelA       Elf64_Rela
+#define Elf_Dyn                Elf64_Dyn
+#define Elf_Word       Elf64_Word
+#define Elf_Sword      Elf64_Sword
+#define Elf_Addr       Elf64_Addr
+#define Elf_Off                Elf64_Off
+#define Elf_Nhdr       Elf64_Nhdr
+#define Elf_Note       Elf64_Note
+
+#define ELF_R_SYM      ELF64_R_SYM
+#define ELF_R_TYPE     ELF64_R_TYPE
+#define ELF_R_INFO     ELF64_R_INFO
+#define ELFCLASS       ELFCLASS64
+
+#define ELF_ST_BIND    ELF64_ST_BIND
+#define ELF_ST_TYPE    ELF64_ST_TYPE
+#define ELF_ST_INFO    ELF64_ST_INFO
+
+#define AuxInfo                Aux64Info
+#endif
+
diff --git a/tools/libxc/xc_evtchn.c b/tools/libxc/xc_evtchn.c
new file mode 100644 (file)
index 0000000..624f5b1
--- /dev/null
@@ -0,0 +1,131 @@
+/******************************************************************************
+ * xc_evtchn.c
+ * 
+ * API for manipulating and accessing inter-domain event channels.
+ * 
+ * Copyright (c) 2004, K A Fraser.
+ */
+
+#include "xc_private.h"
+
+
+static int do_evtchn_op(int xc_handle, evtchn_op_t *op)
+{
+    int ret = -1;
+    privcmd_hypercall_t hypercall;
+
+    hypercall.op     = __HYPERVISOR_event_channel_op;
+    hypercall.arg[0] = (unsigned long)op;
+
+    if ( mlock(op, sizeof(*op)) != 0 )
+    {
+        PERROR("Could not lock memory for Xen hypercall");
+        goto out1;
+    }
+
+    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
+        goto out2;
+
+ out2: (void)munlock(op, sizeof(*op));
+ out1: return ret;
+}
+
+
+int xc_evtchn_bind_interdomain(int xc_handle,
+                               u32 dom1,
+                               u32 dom2,
+                               int *port1,
+                               int *port2)
+{
+    evtchn_op_t op;
+    int         rc;
+
+    op.cmd = EVTCHNOP_bind_interdomain;
+    op.u.bind_interdomain.dom1 = (domid_t)dom1;
+    op.u.bind_interdomain.dom2 = (domid_t)dom2;
+   
+    if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
+    {
+        if ( port1 != NULL )
+            *port1 = op.u.bind_interdomain.port1;
+        if ( port2 != NULL )
+            *port2 = op.u.bind_interdomain.port2;
+    }
+    
+    return rc;
+}
+
+
+int xc_evtchn_bind_virq(int xc_handle,
+                        int virq,
+                        int *port)
+{
+    evtchn_op_t op;
+    int         rc;
+
+    op.cmd = EVTCHNOP_bind_virq;
+    op.u.bind_virq.virq = (u32)virq;
+   
+    if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
+    {
+        if ( port != NULL )
+            *port = op.u.bind_virq.port;
+    }
+    
+    return rc;
+}
+
+
+int xc_evtchn_close(int xc_handle,
+                    u32 dom,
+                    int port)
+{
+    evtchn_op_t op;
+    op.cmd = EVTCHNOP_close;
+    op.u.close.dom  = (domid_t)dom;
+    op.u.close.port = port;
+    return do_evtchn_op(xc_handle, &op);
+}
+
+
+int xc_evtchn_send(int xc_handle,
+                   int local_port)
+{
+    evtchn_op_t op;
+    op.cmd = EVTCHNOP_send;
+    op.u.send.local_port = local_port;
+    return do_evtchn_op(xc_handle, &op);
+}
+
+
+int xc_evtchn_status(int xc_handle,
+                     u32 dom,
+                     int port,
+                     xc_evtchn_status_t *status)
+{
+    evtchn_op_t op;
+    int         rc;
+
+    op.cmd = EVTCHNOP_status;
+    op.u.status.dom  = (domid_t)dom;
+    op.u.status.port = port;
+   
+    if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
+    {
+        switch ( status->status = op.u.status.status )
+        {
+        case EVTCHNSTAT_interdomain:
+            status->u.interdomain.dom  = (u32)op.u.status.u.interdomain.dom;
+            status->u.interdomain.port = op.u.status.u.interdomain.port;
+            break;
+        case EVTCHNSTAT_pirq:
+            status->u.pirq = op.u.status.u.pirq;
+            break;
+        case EVTCHNSTAT_virq:
+            status->u.virq = op.u.status.u.virq;
+            break;
+        }
+    }
+    
+    return rc;
+}
diff --git a/tools/libxc/xc_io.c b/tools/libxc/xc_io.c
new file mode 100644 (file)
index 0000000..b7ce634
--- /dev/null
@@ -0,0 +1,31 @@
+#include "xc_io.h"
+
+void xcio_error(XcIOContext *ctxt, const char *msg, ...){
+  va_list args;
+
+  va_start(args, msg);
+  vfprintf(stdout, msg, args); fprintf(stdout, "\n");
+  IOStream_vprint(ctxt->info, msg, args);
+  IOStream_print(ctxt->info, "\n");
+  va_end(args);
+}
+
+void xcio_info(XcIOContext *ctxt, const char *msg, ...){
+  va_list args;
+
+  if(0 && !(ctxt->flags & XCFLAGS_VERBOSE)) return;
+  va_start(args, msg);
+  vfprintf(stdout, msg, args); fprintf(stdout, "\n");
+  IOStream_vprint(ctxt->info, msg, args);
+  va_end(args);
+}
+
+void xcio_debug(XcIOContext *ctxt, const char *msg, ...){
+  va_list args;
+
+  if(0 && !(ctxt->flags & XCFLAGS_DEBUG)) return;
+  va_start(args, msg);
+  vfprintf(stdout, msg, args); fprintf(stdout, "\n");
+  IOStream_vprint(ctxt->info, msg, args);
+  va_end(args);
+}
diff --git a/tools/libxc/xc_io.h b/tools/libxc/xc_io.h
new file mode 100644 (file)
index 0000000..37febb5
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __XC_XC_IO_H__
+#define __XC_XC_IO_H__
+
+#include "xc_private.h"
+#include "iostream.h"
+
+typedef struct XcIOContext {
+    u32 domain;
+    unsigned flags;
+    IOStream *io;
+    IOStream *info;
+    IOStream *err;
+    char *vmconfig;
+    int vmconfig_n;
+} XcIOContext;
+
+static inline int xcio_read(XcIOContext *ctxt, void *buf, int n){
+    int rc;
+
+    rc = IOStream_read(ctxt->io, buf, n);
+    return (rc == n ? 0 : rc);
+}
+
+static inline int xcio_write(XcIOContext *ctxt, void *buf, int n){
+    int rc;
+
+    rc = IOStream_write(ctxt->io, buf, n);
+    return (rc == n ? 0 : rc);
+}
+
+static inline int xcio_flush(XcIOContext *ctxt){
+    return IOStream_flush(ctxt->io);
+}
+
+extern void xcio_error(XcIOContext *ctxt, const char *msg, ...);
+extern void xcio_info(XcIOContext *ctxt, const char *msg, ...);
+
+#define xcio_perror(_ctxt, _msg...) \
+xcio_error(_ctxt, "(errno %d %s)" _msg, errno, strerror(errno), ## _msg)
+
+#endif /* ! __XC_XC_IO_H__ */
+
+
+
diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c
new file mode 100644 (file)
index 0000000..ceace01
--- /dev/null
@@ -0,0 +1,675 @@
+/******************************************************************************
+ * xc_linux_build.c
+ */
+
+#include "xc_private.h"
+#define ELFSIZE 32
+#include "xc_elf.h"
+#include <zlib.h>
+
+#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
+#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
+
+#define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
+#define round_pgdown(_p)  ((_p)&PAGE_MASK)
+
+static int readelfimage_base_and_size(char *elfbase, 
+                                      unsigned long elfsize,
+                                      unsigned long *pkernstart,
+                                      unsigned long *pkernend,
+                                      unsigned long *pkernentry);
+static int loadelfimage(char *elfbase, int pmh, unsigned long *parray,
+                        unsigned long vstart);
+
+static long get_tot_pages(int xc_handle, u32 domid)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_GETDOMAININFO;
+    op.u.getdomaininfo.domain = (domid_t)domid;
+    op.u.getdomaininfo.ctxt = NULL;
+    return (do_dom0_op(xc_handle, &op) < 0) ? 
+        -1 : op.u.getdomaininfo.tot_pages;
+}
+
+static int get_pfn_list(int xc_handle,
+                        u32 domid, 
+                        unsigned long *pfn_buf, 
+                        unsigned long max_pfns)
+{
+    dom0_op_t op;
+    int ret;
+    op.cmd = DOM0_GETMEMLIST;
+    op.u.getmemlist.domain   = (domid_t)domid;
+    op.u.getmemlist.max_pfns = max_pfns;
+    op.u.getmemlist.buffer   = pfn_buf;
+
+    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
+        return -1;
+
+    ret = do_dom0_op(xc_handle, &op);
+
+    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
+
+    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
+}
+
+static int copy_to_domain_page(int pm_handle,
+                               unsigned long dst_pfn, 
+                               void *src_page)
+{
+    void *vaddr = map_pfn_writeable(pm_handle, dst_pfn);
+    if ( vaddr == NULL )
+        return -1;
+    memcpy(vaddr, src_page, PAGE_SIZE);
+    unmap_pfn(pm_handle, vaddr);
+    return 0;
+}
+
+static int setup_guestos(int xc_handle,
+                         u32 dom,
+                         char *image, unsigned long image_size,
+                         gzFile initrd_gfd, unsigned long initrd_len,
+                         unsigned long nr_pages,
+                         unsigned long *pvsi, unsigned long *pvke,
+                         full_execution_context_t *ctxt,
+                         const char *cmdline,
+                         unsigned long shared_info_frame,
+                         unsigned int control_evtchn,
+                        unsigned long flags)
+{
+    l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
+    l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
+    unsigned long *page_array = NULL;
+    unsigned long l2tab;
+    unsigned long l1tab;
+    unsigned long count, i;
+    extended_start_info_t *start_info;
+    shared_info_t *shared_info;
+    mmu_t *mmu = NULL;
+    int pm_handle=-1, rc;
+
+    unsigned long nr_pt_pages;
+    unsigned long ppt_alloc;
+    unsigned long *physmap, *physmap_e, physmap_pfn;
+
+    unsigned long v_start;
+    unsigned long vkern_start;
+    unsigned long vkern_entry;
+    unsigned long vkern_end;
+    unsigned long vinitrd_start;
+    unsigned long vinitrd_end;
+    unsigned long vphysmap_start;
+    unsigned long vphysmap_end;
+    unsigned long vstartinfo_start;
+    unsigned long vstartinfo_end;
+    unsigned long vstack_start;
+    unsigned long vstack_end;
+    unsigned long vpt_start;
+    unsigned long vpt_end;
+    unsigned long v_end;
+
+    rc = readelfimage_base_and_size(image, image_size, 
+                                    &vkern_start, &vkern_end, &vkern_entry);
+    if ( rc != 0 )
+        goto error_out;
+    
+    /*
+     * Why do we need this? The number of page-table frames depends on the 
+     * size of the bootstrap address space. But the size of the address space 
+     * depends on the number of page-table frames (since each one is mapped 
+     * read-only). We have a pair of simultaneous equations in two unknowns, 
+     * which we solve by exhaustive search.
+     */
+    for ( nr_pt_pages = 2; ; nr_pt_pages++ )
+    {
+        v_start          = vkern_start & ~((1<<22)-1);
+        vinitrd_start    = round_pgup(vkern_end);
+        vinitrd_end      = vinitrd_start + initrd_len;
+        vphysmap_start   = round_pgup(vinitrd_end);
+        vphysmap_end     = vphysmap_start + (nr_pages * sizeof(unsigned long));
+        vpt_start        = round_pgup(vphysmap_end);
+        vpt_end          = vpt_start + (nr_pt_pages * PAGE_SIZE);
+        vstartinfo_start = vpt_end;
+        vstartinfo_end   = vstartinfo_start + PAGE_SIZE;
+        vstack_start     = vstartinfo_end;
+        vstack_end       = vstack_start + PAGE_SIZE;
+        v_end            = (vstack_end + (1<<22)-1) & ~((1<<22)-1);
+        if ( (v_end - vstack_end) < (512 << 10) )
+            v_end += 1 << 22; /* Add extra 4MB to get >= 512kB padding. */
+        if ( (((v_end - v_start) >> L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
+            break;
+    }
+
+    if ( (v_end - v_start) > (nr_pages * PAGE_SIZE) )
+    {
+        printf("Initial guest OS requires too much space\n"
+               "(%luMB is greater than %luMB limit)\n",
+               (v_end-v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20);
+        goto error_out;
+    }
+
+    printf("VIRTUAL MEMORY ARRANGEMENT:\n"
+           " Loaded kernel: %08lx->%08lx\n"
+           " Init. ramdisk: %08lx->%08lx\n"
+           " Phys-Mach map: %08lx->%08lx\n"
+           " Page tables:   %08lx->%08lx\n"
+           " Start info:    %08lx->%08lx\n"
+           " Boot stack:    %08lx->%08lx\n"
+           " TOTAL:         %08lx->%08lx\n",
+           vkern_start, vkern_end, 
+           vinitrd_start, vinitrd_end,
+           vphysmap_start, vphysmap_end,
+           vpt_start, vpt_end,
+           vstartinfo_start, vstartinfo_end,
+           vstack_start, vstack_end,
+           v_start, v_end);
+    printf(" ENTRY ADDRESS: %08lx\n", vkern_entry);
+
+    if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 )
+        goto error_out;
+
+    if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
+    {
+        PERROR("Could not allocate memory");
+        goto error_out;
+    }
+
+    if ( get_pfn_list(xc_handle, dom, page_array, nr_pages) != nr_pages )
+    {
+        PERROR("Could not get the page frame list");
+        goto error_out;
+    }
+
+    loadelfimage(image, pm_handle, page_array, v_start);
+
+    /* Load the initial ramdisk image. */
+    if ( initrd_len != 0 )
+    {
+        for ( i = (vinitrd_start - v_start); 
+              i < (vinitrd_end - v_start); i += PAGE_SIZE )
+        {
+            char page[PAGE_SIZE];
+            if ( gzread(initrd_gfd, page, PAGE_SIZE) == -1 )
+            {
+                PERROR("Error reading initrd image, could not");
+                goto error_out;
+            }
+            copy_to_domain_page(pm_handle, 
+                                page_array[i>>PAGE_SHIFT], page);
+        }
+    }
+
+    if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL )
+        goto error_out;
+
+    /* First allocate page for page dir. */
+    ppt_alloc = (vpt_start - v_start) >> PAGE_SHIFT;
+    l2tab = page_array[ppt_alloc++] << PAGE_SHIFT;
+    ctxt->pt_base = l2tab;
+
+    /* Initialise the page tables. */
+    if ( (vl2tab = map_pfn_writeable(pm_handle, l2tab >> PAGE_SHIFT)) == NULL )
+        goto error_out;
+    memset(vl2tab, 0, PAGE_SIZE);
+    vl2e = &vl2tab[l2_table_offset(v_start)];
+    for ( count = 0; count < ((v_end-v_start)>>PAGE_SHIFT); count++ )
+    {    
+        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
+        {
+            l1tab = page_array[ppt_alloc++] << PAGE_SHIFT;
+            if ( vl1tab != NULL )
+                unmap_pfn(pm_handle, vl1tab);
+            if ( (vl1tab = map_pfn_writeable(pm_handle, 
+                                             l1tab >> PAGE_SHIFT)) == NULL )
+                goto error_out;
+            memset(vl1tab, 0, PAGE_SIZE);
+            vl1e = &vl1tab[l1_table_offset(v_start + (count<<PAGE_SHIFT))];
+            *vl2e++ = l1tab | L2_PROT;
+        }
+
+        *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
+        if ( (count >= ((vpt_start-v_start)>>PAGE_SHIFT)) && 
+             (count <  ((vpt_end  -v_start)>>PAGE_SHIFT)) )
+            *vl1e &= ~_PAGE_RW;
+        vl1e++;
+    }
+    unmap_pfn(pm_handle, vl1tab);
+    unmap_pfn(pm_handle, vl2tab);
+
+    /* Write the phys->machine and machine->phys table entries. */
+    physmap_pfn = (vphysmap_start - v_start) >> PAGE_SHIFT;
+    physmap = physmap_e = 
+        map_pfn_writeable(pm_handle, page_array[physmap_pfn++]);
+    for ( count = 0; count < nr_pages; count++ )
+    {
+        if ( add_mmu_update(xc_handle, mmu,
+                            (page_array[count] << PAGE_SHIFT) | 
+                            MMU_MACHPHYS_UPDATE, count) )
+            goto error_out;
+        *physmap_e++ = page_array[count];
+        if ( ((unsigned long)physmap_e & (PAGE_SIZE-1)) == 0 )
+        {
+            unmap_pfn(pm_handle, physmap);
+            physmap = physmap_e = 
+                map_pfn_writeable(pm_handle, page_array[physmap_pfn++]);
+        }
+    }
+    unmap_pfn(pm_handle, physmap);
+    
+    /*
+     * Pin down l2tab addr as page dir page - causes hypervisor to provide
+     * correct protection for the page
+     */ 
+    if ( add_mmu_update(xc_handle, mmu,
+                        l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L2_TABLE) )
+        goto error_out;
+
+    start_info = map_pfn_writeable(
+        pm_handle, page_array[(vstartinfo_start-v_start)>>PAGE_SHIFT]);
+    memset(start_info, 0, sizeof(*start_info));
+    start_info->nr_pages     = nr_pages;
+    start_info->shared_info  = shared_info_frame << PAGE_SHIFT;
+    start_info->flags        = flags;
+    start_info->pt_base      = vpt_start;
+    start_info->nr_pt_frames = nr_pt_pages;
+    start_info->mfn_list     = vphysmap_start;
+    start_info->domain_controller_evtchn = control_evtchn;
+    if ( initrd_len != 0 )
+    {
+        start_info->mod_start    = vinitrd_start;
+        start_info->mod_len      = initrd_len;
+    }
+    strncpy(start_info->cmd_line, cmdline, MAX_CMDLINE);
+    start_info->cmd_line[MAX_CMDLINE-1] = '\0';
+    unmap_pfn(pm_handle, start_info);
+
+    /* shared_info page starts its life empty. */
+    shared_info = map_pfn_writeable(pm_handle, shared_info_frame);
+    memset(shared_info, 0, sizeof(shared_info_t));
+    /* Mask all upcalls... */
+    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
+        shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
+    unmap_pfn(pm_handle, shared_info);
+
+    /* Send the page update requests down to the hypervisor. */
+    if ( finish_mmu_updates(xc_handle, mmu) )
+        goto error_out;
+
+    free(mmu);
+    (void)close_pfn_mapper(pm_handle);
+    free(page_array);
+
+    *pvsi = vstartinfo_start;
+    *pvke = vkern_entry;
+
+    return 0;
+
+ error_out:
+    if ( mmu != NULL )
+        free(mmu);
+    if ( pm_handle >= 0 )
+        (void)close_pfn_mapper(pm_handle);
+    if ( page_array != NULL )
+        free(page_array);
+    return -1;
+}
+
+static unsigned long get_filesz(int fd)
+{
+    u16 sig;
+    u32 _sz = 0;
+    unsigned long sz;
+
+    lseek(fd, 0, SEEK_SET);
+    read(fd, &sig, sizeof(sig));
+    sz = lseek(fd, 0, SEEK_END);
+    if ( sig == 0x8b1f ) /* GZIP signature? */
+    {
+        lseek(fd, -4, SEEK_END);
+        read(fd, &_sz, 4);
+        sz = _sz;
+    }
+    lseek(fd, 0, SEEK_SET);
+
+    return sz;
+}
+
+static char *read_kernel_image(const char *filename, unsigned long *size)
+{
+    int kernel_fd = -1;
+    gzFile kernel_gfd = NULL;
+    char *image = NULL;
+    unsigned int bytes;
+
+    if ( (kernel_fd = open(filename, O_RDONLY)) < 0 )
+    {
+        PERROR("Could not open kernel image");
+        goto out;
+    }
+
+    *size = get_filesz(kernel_fd);
+
+    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
+    {
+        PERROR("Could not allocate decompression state for state file");
+        goto out;
+    }
+
+    if ( (image = malloc(*size)) == NULL )
+    {
+        PERROR("Could not allocate memory for kernel image");
+        goto out;
+    }
+
+    if ( (bytes = gzread(kernel_gfd, image, *size)) != *size )
+    {
+        PERROR("Error reading kernel image, could not"
+               " read the whole image (%d != %ld).", bytes, *size);
+        free(image);
+        image = NULL;
+    }
+
+ out:
+    if ( kernel_gfd != NULL )
+        gzclose(kernel_gfd);
+    else if ( kernel_fd >= 0 )
+        close(kernel_fd);
+    return image;
+}
+
+int xc_linux_build(int xc_handle,
+                   u32 domid,
+                   const char *image_name,
+                   const char *ramdisk_name,
+                   const char *cmdline,
+                   unsigned int control_evtchn,
+                   unsigned long flags)
+{
+    dom0_op_t launch_op, op;
+    int initrd_fd = -1;
+    gzFile initrd_gfd = NULL;
+    int rc, i;
+    full_execution_context_t st_ctxt, *ctxt = &st_ctxt;
+    unsigned long nr_pages;
+    char         *image = NULL;
+    unsigned long image_size, initrd_size=0;
+    unsigned long vstartinfo_start, vkern_entry;
+
+    if ( (nr_pages = get_tot_pages(xc_handle, domid)) < 0 )
+    {
+        PERROR("Could not find total pages for domain");
+        goto error_out;
+    }
+
+    if ( (image = read_kernel_image(image_name, &image_size)) == NULL )
+        goto error_out;
+
+    if ( (ramdisk_name != NULL) && (strlen(ramdisk_name) != 0) )
+    {
+        if ( (initrd_fd = open(ramdisk_name, O_RDONLY)) < 0 )
+        {
+            PERROR("Could not open the initial ramdisk image");
+            goto error_out;
+        }
+
+        initrd_size = get_filesz(initrd_fd);
+
+        if ( (initrd_gfd = gzdopen(initrd_fd, "rb")) == NULL )
+        {
+            PERROR("Could not allocate decompression state for initrd");
+            goto error_out;
+        }
+    }
+
+    if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
+    {   
+        PERROR("Unable to mlock ctxt");
+        return 1;
+    }
+
+    op.cmd = DOM0_GETDOMAININFO;
+    op.u.getdomaininfo.domain = (domid_t)domid;
+    op.u.getdomaininfo.ctxt = ctxt;
+    if ( (do_dom0_op(xc_handle, &op) < 0) || 
+         ((u32)op.u.getdomaininfo.domain != domid) )
+    {
+        PERROR("Could not get info on domain");
+        goto error_out;
+    }
+    if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ||
+         (ctxt->pt_base != 0) )
+    {
+        ERROR("Domain is already constructed");
+        goto error_out;
+    }
+
+    if ( setup_guestos(xc_handle, domid, image, image_size, 
+                       initrd_gfd, initrd_size, nr_pages, 
+                       &vstartinfo_start, &vkern_entry,
+                       ctxt, cmdline,
+                       op.u.getdomaininfo.shared_info_frame,
+                       control_evtchn, flags) < 0 )
+    {
+        ERROR("Error constructing guest OS");
+        goto error_out;
+    }
+
+    if ( initrd_fd >= 0 )
+        close(initrd_fd);
+    if ( initrd_gfd )
+        gzclose(initrd_gfd);
+    if ( image != NULL )
+        free(image);
+
+    ctxt->flags = 0;
+
+    /*
+     * Initial register values:
+     *  DS,ES,FS,GS = FLAT_GUESTOS_DS
+     *       CS:EIP = FLAT_GUESTOS_CS:start_pc
+     *       SS:ESP = FLAT_GUESTOS_DS:start_stack
+     *          ESI = start_info
+     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
+     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
+     */
+    ctxt->cpu_ctxt.ds = FLAT_GUESTOS_DS;
+    ctxt->cpu_ctxt.es = FLAT_GUESTOS_DS;
+    ctxt->cpu_ctxt.fs = FLAT_GUESTOS_DS;
+    ctxt->cpu_ctxt.gs = FLAT_GUESTOS_DS;
+    ctxt->cpu_ctxt.ss = FLAT_GUESTOS_DS;
+    ctxt->cpu_ctxt.cs = FLAT_GUESTOS_CS;
+    ctxt->cpu_ctxt.eip = vkern_entry;
+    ctxt->cpu_ctxt.esp = vstartinfo_start;
+    ctxt->cpu_ctxt.esi = vstartinfo_start;
+    ctxt->cpu_ctxt.eflags = (1<<9) | (1<<2);
+
+    /* FPU is set up to default initial state. */
+    memset(ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
+
+    /* Virtual IDT is empty at start-of-day. */
+    for ( i = 0; i < 256; i++ )
+    {
+        ctxt->trap_ctxt[i].vector = i;
+        ctxt->trap_ctxt[i].cs     = FLAT_GUESTOS_CS;
+    }
+    ctxt->fast_trap_idx = 0;
+
+    /* No LDT. */
+    ctxt->ldt_ents = 0;
+    
+    /* Use the default Xen-provided GDT. */
+    ctxt->gdt_ents = 0;
+
+    /* Ring 1 stack is the initial stack. */
+    ctxt->guestos_ss  = FLAT_GUESTOS_DS;
+    ctxt->guestos_esp = vstartinfo_start;
+
+    /* No debugging. */
+    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
+
+    /* No callback handlers. */
+    ctxt->event_callback_cs     = FLAT_GUESTOS_CS;
+    ctxt->event_callback_eip    = 0;
+    ctxt->failsafe_callback_cs  = FLAT_GUESTOS_CS;
+    ctxt->failsafe_callback_eip = 0;
+
+    memset( &launch_op, 0, sizeof(launch_op) );
+
+    launch_op.u.builddomain.domain   = (domid_t)domid;
+    launch_op.u.builddomain.ctxt = ctxt;
+
+    launch_op.cmd = DOM0_BUILDDOMAIN;
+    rc = do_dom0_op(xc_handle, &launch_op);
+    
+    return rc;
+
+ error_out:
+    if ( initrd_gfd != NULL )
+        gzclose(initrd_gfd);
+    else if ( initrd_fd >= 0 )
+        close(initrd_fd);
+    if ( image != NULL )
+        free(image);
+
+    return -1;
+}
+
+static inline int is_loadable_phdr(Elf_Phdr *phdr)
+{
+    return ((phdr->p_type == PT_LOAD) &&
+            ((phdr->p_flags & (PF_W|PF_X)) != 0));
+}
+
+static int readelfimage_base_and_size(char *elfbase, 
+                                      unsigned long elfsize,
+                                      unsigned long *pkernstart,
+                                      unsigned long *pkernend,
+                                      unsigned long *pkernentry)
+{
+    Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
+    Elf_Phdr *phdr;
+    Elf_Shdr *shdr;
+    unsigned long kernstart = ~0UL, kernend=0UL;
+    char *shstrtab, *guestinfo;
+    int h;
+
+    if ( !IS_ELF(*ehdr) )
+    {
+        ERROR("Kernel image does not have an ELF header.");
+        return -EINVAL;
+    }
+
+    if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize )
+    {
+        ERROR("ELF program headers extend beyond end of image.");
+        return -EINVAL;
+    }
+
+    if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize )
+    {
+        ERROR("ELF section headers extend beyond end of image.");
+        return -EINVAL;
+    }
+
+    /* Find the section-header strings table. */
+    if ( ehdr->e_shstrndx == SHN_UNDEF )
+    {
+        ERROR("ELF image has no section-header strings table (shstrtab).");
+        return -EINVAL;
+    }
+    shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + 
+                        (ehdr->e_shstrndx*ehdr->e_shentsize));
+    shstrtab = elfbase + shdr->sh_offset;
+    
+    /* Find the special '__xen_guest' section and check its contents. */
+    for ( h = 0; h < ehdr->e_shnum; h++ )
+    {
+        shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + (h*ehdr->e_shentsize));
+        if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 )
+            continue;
+        guestinfo = elfbase + shdr->sh_offset;
+        if ( (strstr(guestinfo, "GUEST_OS=linux") == NULL) ||
+             (strstr(guestinfo, "XEN_VER=1.3") == NULL) )
+        {
+            ERROR("Will only load Linux images built for Xen v1.3");
+            ERROR("Actually saw: '%s'", guestinfo);
+            return -EINVAL;
+        }
+        break;
+    }
+    if ( h == ehdr->e_shnum )
+    {
+        ERROR("Not a Xen-ELF image: '__xen_guest' section not found.");
+        return -EINVAL;
+    }
+
+    for ( h = 0; h < ehdr->e_phnum; h++ ) 
+    {
+        phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
+        if ( !is_loadable_phdr(phdr) )
+            continue;
+        if ( phdr->p_vaddr < kernstart )
+            kernstart = phdr->p_vaddr;
+        if ( (phdr->p_vaddr + phdr->p_memsz) > kernend )
+            kernend = phdr->p_vaddr + phdr->p_memsz;
+    }
+
+    if ( (kernstart > kernend) || 
+         (ehdr->e_entry < kernstart) || 
+         (ehdr->e_entry > kernend) )
+    {
+        ERROR("Malformed ELF image.");
+        return -EINVAL;
+    }
+
+    *pkernstart = kernstart;
+    *pkernend   = kernend;
+    *pkernentry = ehdr->e_entry;
+
+    return 0;
+}
+
+static int loadelfimage(char *elfbase, int pmh, unsigned long *parray,
+                        unsigned long vstart)
+{
+    Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
+    Elf_Phdr *phdr;
+    int h;
+
+    char         *va;
+    unsigned long pa, done, chunksz;
+
+    for ( h = 0; h < ehdr->e_phnum; h++ ) 
+    {
+        phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
+        if ( !is_loadable_phdr(phdr) )
+            continue;
+        
+        for ( done = 0; done < phdr->p_filesz; done += chunksz )
+        {
+            pa = (phdr->p_vaddr + done) - vstart;
+            va = map_pfn_writeable(pmh, parray[pa>>PAGE_SHIFT]);
+            va += pa & (PAGE_SIZE-1);
+            chunksz = phdr->p_filesz - done;
+            if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
+                chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
+            memcpy(va, elfbase + phdr->p_offset + done, chunksz);
+            unmap_pfn(pmh, va);
+        }
+
+        for ( ; done < phdr->p_memsz; done += chunksz )
+        {
+            pa = (phdr->p_vaddr + done) - vstart;
+            va = map_pfn_writeable(pmh, parray[pa>>PAGE_SHIFT]);
+            va += pa & (PAGE_SIZE-1);
+            chunksz = phdr->p_memsz - done;
+            if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
+                chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
+            memset(va, 0, chunksz);
+            unmap_pfn(pmh, va);            
+        }
+    }
+
+    return 0;
+}
+
diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c
new file mode 100644 (file)
index 0000000..badba75
--- /dev/null
@@ -0,0 +1,600 @@
+/******************************************************************************
+ * xc_linux_restore.c
+ * 
+ * Restore the state of a Linux session.
+ * 
+ * Copyright (c) 2003, K A Fraser.
+ */
+
+#include "xc_private.h"
+#include <asm-xen/suspend.h>
+
+#define MAX_BATCH_SIZE 1024
+
+#define DEBUG 0
+
+#if DEBUG
+#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+
+
+static int get_pfn_list(int xc_handle,
+                        u32 domain_id, 
+                        unsigned long *pfn_buf, 
+                        unsigned long max_pfns)
+{
+    dom0_op_t op;
+    int ret;
+    op.cmd = DOM0_GETMEMLIST;
+    op.u.getmemlist.domain   = (domid_t)domain_id;
+    op.u.getmemlist.max_pfns = max_pfns;
+    op.u.getmemlist.buffer   = pfn_buf;
+
+    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
+    {
+        PERROR("Could not lock pfn list buffer");
+        return -1;
+    }    
+
+    ret = do_dom0_op(xc_handle, &op);
+
+    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
+
+    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
+}
+
+/** Read the vmconfig string from the state input.
+ * It is stored as a 4-byte count 'n' followed by n bytes.
+ * The config data is stored in a new string in 'ioctxt->vmconfig',
+ * and is null-terminated. The count is stored in 'ioctxt->vmconfig_n'.
+ *
+ * @param ioctxt i/o context
+ * @return 0 on success, non-zero on error.
+ */
+static int read_vmconfig(XcIOContext *ioctxt){
+    int err = -1;
+    if(xcio_read(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))){
+        goto exit;
+    }
+    ioctxt->vmconfig = malloc(ioctxt->vmconfig_n + 1);
+    if(!ioctxt->vmconfig) goto exit;
+    if(xcio_read(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)){
+        goto exit;
+    }
+    ioctxt->vmconfig[ioctxt->vmconfig_n] = '\0';
+    err = 0;
+  exit:
+    if(err){
+        if(ioctxt->vmconfig){
+            free(ioctxt->vmconfig);
+        }
+        ioctxt->vmconfig = NULL;
+        ioctxt->vmconfig_n = 0;
+    }
+    return err;
+}
+
+int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
+{
+    dom0_op_t op;
+    int rc = 1, i, n, k;
+    unsigned long mfn, pfn, xpfn;
+    unsigned int prev_pc, this_pc;
+    u32 dom = ioctxt->domain;
+    int verify = 0; 
+
+    /* Number of page frames in use by this Linux session. */
+    unsigned long nr_pfns;
+
+    /* The new domain's shared-info frame number. */
+    unsigned long shared_info_frame;
+    unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */
+    
+    /* A copy of the CPU context of the guest. */
+    full_execution_context_t ctxt;
+
+    /* First 16 bytes of the state file must contain 'LinuxGuestRecord'. */
+    char signature[16];
+    
+    /* A copy of the domain's name. */
+    char name[MAX_DOMAIN_NAME];
+
+    /* A table containg the type of each PFN (/not/ MFN!). */
+    unsigned long *pfn_type = NULL;
+
+    /* A table of MFNs to map in the current region */
+    unsigned long *region_mfn = NULL;
+
+    /* A temporary mapping, and a copy, of one frame of guest memory. */
+    unsigned long *ppage;
+
+    /* A copy of the pfn-to-mfn table frame list. */
+    unsigned long pfn_to_mfn_frame_list[1024];
+
+    /* A table mapping each PFN to its new MFN. */
+    unsigned long *pfn_to_mfn_table = NULL;
+
+    /* used by mapper for updating the domain's copy of the table */
+    unsigned long *live_pfn_to_mfn_table = NULL;
+
+    /* A temporary mapping of the guest's suspend record. */
+    suspend_record_t *p_srec;
+
+    char *region_base;
+
+    mmu_t *mmu = NULL;
+
+    int pm_handle = -1;
+
+    /* used by debug verify code */
+    unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
+
+    if ( mlock(&ctxt, sizeof(ctxt) ) ) {   
+        /* needed for when we do the build dom0 op, 
+           but might as well do early */
+        PERROR("Unable to mlock ctxt");
+        return 1;
+    }
+
+    /* Start writing out the saved-domain record. */
+    if ( xcio_read(ioctxt, signature, 16) ||
+         (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) {
+        xcio_error(ioctxt, "Unrecognised state format -- no signature found");
+        goto out;
+    }
+
+    if ( xcio_read(ioctxt, name,                  sizeof(name)) ||
+         xcio_read(ioctxt, &nr_pfns,              sizeof(unsigned long)) ||
+         xcio_read(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ) {
+        xcio_error(ioctxt, "Error reading header");
+        goto out;
+    }
+
+    if(read_vmconfig(ioctxt)){
+        xcio_error(ioctxt, "Error writing vmconfig");
+        goto out;
+    }
+
+    for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) {
+        if ( name[i] == '\0' ) break;
+        if ( name[i] & 0x80 )
+        {
+            xcio_error(ioctxt, "Random characters in domain name");
+            goto out;
+        }
+    }
+    name[MAX_DOMAIN_NAME-1] = '\0';
+
+    if ( nr_pfns > 1024*1024 ) {
+        xcio_error(ioctxt, "Invalid state file -- pfn count out of range");
+        goto out;
+    }
+
+    /* We want zeroed memory so use calloc rather than malloc. */
+    pfn_to_mfn_table = calloc(1, 4 * nr_pfns);
+    pfn_type         = calloc(1, 4 * nr_pfns);    
+    region_mfn       = calloc(1, 4 * MAX_BATCH_SIZE);    
+
+    if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) || 
+         (region_mfn == NULL) ) {
+        errno = ENOMEM;
+        goto out;
+    }
+    
+    if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) ) {
+        xcio_error(ioctxt, "Could not mlock region_mfn");
+        goto out;
+    }
+
+    /* Set the domain's name to that from the restore file */
+    if ( xc_domain_setname( xc_handle, dom, name ) ) {
+        xcio_error(ioctxt, "Could not set domain name");
+        goto out;
+    }
+
+    /* Set the domain's initial memory allocation 
+       to that from the restore file */
+
+    if ( xc_domain_setinitialmem(xc_handle, dom, 
+                                 nr_pfns * (PAGE_SIZE / 1024)) )
+    {
+        xcio_error(ioctxt, "Could not set domain initial memory");
+        goto out;
+    }
+
+    /* Get the domain's shared-info frame. */
+    op.cmd = DOM0_GETDOMAININFO;
+    op.u.getdomaininfo.domain = (domid_t)dom;
+    op.u.getdomaininfo.ctxt = NULL;
+    if ( do_dom0_op(xc_handle, &op) < 0 ) {
+        xcio_error(ioctxt, "Could not get information on new domain");
+        goto out;
+    }
+    shared_info_frame = op.u.getdomaininfo.shared_info_frame;
+
+    if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 )
+        goto out;
+
+
+
+    /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
+    if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) {
+        xcio_error(ioctxt, "Did not read correct number of frame numbers for new dom");
+        goto out;
+    }
+
+    if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) {
+        xcio_error(ioctxt, "Could not initialise for MMU updates");
+        goto out;
+    }
+
+    xcio_info(ioctxt, "Reloading memory pages:   0%%");
+
+    /*
+     * Now simply read each saved frame into its new machine frame.
+     * We uncanonicalise page tables as we go.
+     */
+    prev_pc = 0;
+
+    n=0;
+    while(1) {
+        int j;
+        unsigned long region_pfn_type[MAX_BATCH_SIZE];
+
+        this_pc = (n * 100) / nr_pfns;
+        if ( (this_pc - prev_pc) >= 5 ) {
+            xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc);
+            prev_pc = this_pc;
+        }
+
+        if ( xcio_read(ioctxt, &j, sizeof(int)) ) {
+            xcio_error(ioctxt, "Error when reading from state file");
+            goto out;
+        }
+
+        DPRINTF("batch %d\n",j);
+        if ( j == -1 ) {
+            verify = 1;
+            printf("Entering page verify mode\n");
+            continue;
+        }
+
+        if ( j == 0 ) break;  /* our work here is done */
+
+        if( j > MAX_BATCH_SIZE ) {
+            xcio_error(ioctxt, "Max batch size exceeded. Giving up.");
+            goto out;
+        }
+        if ( xcio_read(ioctxt, region_pfn_type, j*sizeof(unsigned long)) ) {
+            xcio_error(ioctxt, "Error when reading from state file");
+            goto out;
+        }
+
+        for(i=0; i<j; i++) {
+            if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) {
+                region_mfn[i] = 0; /* we know map will fail, but don't care */
+            } else {  
+                pfn = region_pfn_type[i] & ~LTAB_MASK;
+                region_mfn[i] = pfn_to_mfn_table[pfn];
+            }          
+        }
+        if ( (region_base = mfn_mapper_map_batch( xc_handle, dom, 
+                                                  PROT_WRITE,
+                                                  region_mfn,
+                                                  j )) == 0) {
+            xcio_error(ioctxt, "map batch failed");
+            goto out;
+        }
+
+        for(i=0;i<j;i++) {
+            unsigned long *ppage;
+
+            pfn = region_pfn_type[i] & ~LTAB_MASK;
+
+            if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) continue;
+
+            if (pfn>nr_pfns) {
+                xcio_error(ioctxt, "pfn out of range");
+                goto out;
+            }
+
+            region_pfn_type[i] &= LTAB_MASK;
+
+            pfn_type[pfn] = region_pfn_type[i];
+
+            mfn = pfn_to_mfn_table[pfn];
+
+            if ( verify ) {
+                ppage = (unsigned long*) buf;  /* debug case */
+            } else {
+                ppage = (unsigned long*) (region_base + i*PAGE_SIZE);
+            }
+
+            if ( xcio_read(ioctxt, ppage, PAGE_SIZE) ) {
+                xcio_error(ioctxt, "Error when reading from state file");
+                goto out;
+            }
+
+            switch( region_pfn_type[i] ) {
+            case 0:
+                break;
+
+            case L1TAB:
+            {
+                for ( k = 0; k < 1024; k++ ) {
+                    if ( ppage[k] & _PAGE_PRESENT ) {
+                        xpfn = ppage[k] >> PAGE_SHIFT;
+
+                        if ( xpfn >= nr_pfns ) {
+                            xcio_error(ioctxt, "Frame number in type %lu page table is "
+                                  "out of range. i=%d k=%d pfn=0x%lx "
+                                  "nr_pfns=%lu", region_pfn_type[i]>>28, i, 
+                                  k, xpfn, nr_pfns);
+                            goto out;
+                        }
+
+                        ppage[k] &= (PAGE_SIZE - 1) & 
+                            ~(_PAGE_GLOBAL | _PAGE_PAT);
+                        ppage[k] |= pfn_to_mfn_table[xpfn] << PAGE_SHIFT;
+                    }
+                }
+            }
+            break;
+
+            case L2TAB:
+            {
+                for ( k = 0; 
+                      k < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); 
+                      k++ ) {
+                    if ( ppage[k] & _PAGE_PRESENT ) {
+                        xpfn = ppage[k] >> PAGE_SHIFT;
+
+                        if ( xpfn >= nr_pfns ) {
+                            xcio_error(ioctxt, "Frame number in type %lu page table is "
+                                  "out of range. i=%d k=%d pfn=%lu nr_pfns=%lu",
+                                  region_pfn_type[i]>>28, i, k, xpfn, nr_pfns);
+
+                            goto out;
+                        }
+
+                        ppage[k] &= (PAGE_SIZE - 1) & 
+                            ~(_PAGE_GLOBAL | _PAGE_PSE);
+                        ppage[k] |= pfn_to_mfn_table[xpfn] << PAGE_SHIFT;
+                    }
+                }
+            }
+            break;
+
+            default:
+                xcio_error(ioctxt, "Bogus page type %lx page table is out of range."
+                      " i=%d nr_pfns=%lu", region_pfn_type[i], i, nr_pfns);
+                goto out;
+
+            } /* end of page type switch statement */
+
+            if ( verify ) {
+                int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE );
+                if (res) {
+                    int v;
+                    printf("************** pfn=%lx type=%lx gotcs=%08lx "
+                           "actualcs=%08lx\n", pfn, pfn_type[pfn], 
+                           csum_page(region_base + i*PAGE_SIZE), 
+                           csum_page(buf));
+                    for ( v = 0; v < 4; v++ ) {
+                        unsigned long *p = (unsigned long *)
+                            (region_base + i*PAGE_SIZE);
+                        if ( buf[v] != p[v] )
+                            printf("    %d: %08lx %08lx\n",
+                                   v, buf[v], p[v] );
+                    }
+                }
+            }
+
+            if ( add_mmu_update(xc_handle, mmu,
+                                (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, pfn) ) {
+                printf("machpys mfn=%ld pfn=%ld\n",mfn,pfn);
+                goto out;
+            }
+
+        } /* end of 'batch' for loop */
+
+        munmap( region_base, j*PAGE_SIZE );
+        n+=j; /* crude stats */
+    }
+
+    printf("Received all pages\n");
+
+    DPRINTF("Received all pages\n");
+
+    /*
+     * Pin page tables. Do this after writing to them as otherwise Xen
+     * will barf when doing the type-checking.
+     */
+    for ( i = 0; i < nr_pfns; i++ ) {
+        if ( pfn_type[i] == L1TAB ) {
+            if ( add_mmu_update(xc_handle, mmu,
+                                (pfn_to_mfn_table[i]<<PAGE_SHIFT) | 
+                                MMU_EXTENDED_COMMAND,
+                                MMUEXT_PIN_L1_TABLE) ) {
+                printf("ERR pin L1 pfn=%lx mfn=%lx\n",
+                       (unsigned long)i, pfn_to_mfn_table[i]);
+                goto out;
+            }
+        } else if ( pfn_type[i] == L2TAB ) {
+            if ( add_mmu_update(xc_handle, mmu,
+                                (pfn_to_mfn_table[i]<<PAGE_SHIFT) | 
+                                MMU_EXTENDED_COMMAND,
+                                MMUEXT_PIN_L2_TABLE) ) {
+                printf("ERR pin L2 pfn=%lx mfn=%lx\n",
+                       (unsigned long)i, pfn_to_mfn_table[i]);
+                goto out;
+            }
+        }
+    }
+
+    if ( finish_mmu_updates(xc_handle, mmu) ) goto out;
+
+    xcio_info(ioctxt, "\b\b\b\b100%%\nMemory reloaded.\n");
+
+
+    if ( xcio_read(ioctxt, &ctxt,                 sizeof(ctxt)) ||
+         xcio_read(ioctxt, shared_info,           PAGE_SIZE) ) {
+        xcio_error(ioctxt, "Error when reading from state file");
+        goto out;
+    }
+
+    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
+    pfn = ctxt.cpu_ctxt.esi;
+    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) )
+    {
+        xcio_error(ioctxt, "Suspend record frame number is bad");
+        goto out;
+    }
+    ctxt.cpu_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
+    p_srec = map_pfn_writeable(pm_handle, mfn);
+    p_srec->resume_info.nr_pages    = nr_pfns;
+    p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
+    p_srec->resume_info.flags       = 0;
+    unmap_pfn(pm_handle, p_srec);
+
+    /* Uncanonicalise each GDT frame number. */
+    if ( ctxt.gdt_ents > 8192 ) {
+        xcio_error(ioctxt, "GDT entry count out of range");
+        goto out;
+    }
+    for ( i = 0; i < ctxt.gdt_ents; i += 512 ) {
+        pfn = ctxt.gdt_frames[i];
+        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) {
+            xcio_error(ioctxt, "GDT frame number is bad");
+            goto out;
+        }
+        ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn];
+    }
+
+    /* Uncanonicalise the page table base pointer. */
+    pfn = ctxt.pt_base >> PAGE_SHIFT;
+    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) {
+        printf("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx\n",
+               pfn, nr_pfns, pfn_type[pfn], (unsigned long)L2TAB);
+        xcio_error(ioctxt, "PT base is bad.");
+        goto out;
+    }
+    ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
+
+
+    /* clear any pending events and the selector */
+    memset( &(((shared_info_t *)shared_info)->evtchn_pending[0]),
+            0, sizeof (((shared_info_t *)shared_info)->evtchn_pending)+
+            sizeof(((shared_info_t *)shared_info)->evtchn_pending_sel) );
+
+    /* Copy saved contents of shared-info page. No checking needed. */
+    ppage = map_pfn_writeable(pm_handle, shared_info_frame);
+    memcpy(ppage, shared_info, sizeof(shared_info_t));
+    unmap_pfn(pm_handle, ppage);
+
+
+    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
+    for ( i = 0; i < (nr_pfns+1023)/1024; i++ ) {
+        unsigned long pfn, mfn;
+
+        pfn = pfn_to_mfn_frame_list[i];
+        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) {
+            xcio_error(ioctxt, "PFN-to-MFN frame number is bad");
+            goto out;
+        }
+        mfn = pfn_to_mfn_table[pfn];
+        pfn_to_mfn_frame_list[i] = mfn;
+    }
+    
+    if ( (live_pfn_to_mfn_table = 
+          mfn_mapper_map_batch(xc_handle, dom, 
+                               PROT_WRITE,
+                               pfn_to_mfn_frame_list,
+                               (nr_pfns+1023)/1024 )) == 0 ) {
+        xcio_error(ioctxt, "Couldn't map pfn_to_mfn table");
+        goto out;
+    }
+
+    memcpy( live_pfn_to_mfn_table, pfn_to_mfn_table, 
+            nr_pfns*sizeof(unsigned long) );
+
+    munmap( live_pfn_to_mfn_table, ((nr_pfns+1023)/1024)*PAGE_SIZE );
+
+    /*
+     * Safety checking of saved context:
+     *  1. cpu_ctxt is fine, as Xen checks that on context switch.
+     *  2. fpu_ctxt is fine, as it can't hurt Xen.
+     *  3. trap_ctxt needs the code selectors checked.
+     *  4. fast_trap_idx is checked by Xen.
+     *  5. ldt base must be page-aligned, no more than 8192 ents, ...
+     *  6. gdt already done, and further checking is done by Xen.
+     *  7. check that guestos_ss is safe.
+     *  8. pt_base is already done.
+     *  9. debugregs are checked by Xen.
+     *  10. callback code selectors need checking.
+     */
+    for ( i = 0; i < 256; i++ ) {
+        ctxt.trap_ctxt[i].vector = i;
+        if ( (ctxt.trap_ctxt[i].cs & 3) == 0 )
+            ctxt.trap_ctxt[i].cs = FLAT_GUESTOS_CS;
+    }
+    if ( (ctxt.guestos_ss & 3) == 0 ){
+        ctxt.guestos_ss = FLAT_GUESTOS_DS;
+    }
+    if ( (ctxt.event_callback_cs & 3) == 0 ){
+        ctxt.event_callback_cs = FLAT_GUESTOS_CS;
+    }
+    if ( (ctxt.failsafe_callback_cs & 3) == 0 ){
+        ctxt.failsafe_callback_cs = FLAT_GUESTOS_CS;
+    }
+    if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
+         (ctxt.ldt_ents > 8192) ||
+         (ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
+         ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) )
+    {
+        xcio_error(ioctxt, "Bad LDT base or size");
+        goto out;
+    }
+   
+    op.cmd = DOM0_BUILDDOMAIN;
+    op.u.builddomain.domain   = (domid_t)dom;
+    op.u.builddomain.ctxt = &ctxt;
+    rc = do_dom0_op(xc_handle, &op);
+
+    /* don't start the domain as we have console etc to set up */
+  
+    if( rc == 0 ) {
+        /* Success: print the domain id. */
+        xcio_info(ioctxt, "DOM=%lu\n", dom);
+        return 0;
+    }
+
+
+ out:
+    if ( (rc != 0) && (dom != 0) ){
+        xc_domain_destroy(xc_handle, dom);
+    }
+    if ( mmu != NULL ){
+        free(mmu);
+    }
+    if ( pm_handle >= 0 ){
+        (void)close_pfn_mapper(pm_handle);
+    }
+    if ( pfn_to_mfn_table != NULL ){
+        free(pfn_to_mfn_table);
+    }
+    if ( pfn_type != NULL ){
+        free(pfn_type);
+    }
+
+    if ( rc == 0 ){
+        ioctxt->domain = dom;
+    }
+    DPRINTF("Restore exit with rc=%d\n",rc);
+    return rc;
+}
diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c
new file mode 100644 (file)
index 0000000..c74e209
--- /dev/null
@@ -0,0 +1,840 @@
+/******************************************************************************
+ * xc_linux_save.c
+ * 
+ * Save the state of a running Linux session.
+ * 
+ * Copyright (c) 2003, K A Fraser.
+ */
+
+#include <sys/time.h>
+#include "xc_private.h"
+#include <asm-xen/suspend.h>
+
+#define BATCH_SIZE 1024   /* 1024 pages (4MB) at a time */
+
+#define DEBUG 0
+#define DDEBUG 0
+
+#if DEBUG
+#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+
+#if DDEBUG
+#define DDPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DDPRINTF(_f, _a...) ((void)0)
+#endif
+
+/*
+ * Returns TRUE if the given machine frame number has a unique mapping
+ * in the guest's pseudophysical map.
+ * 0x80000000-3 mark the shared_info, and blk/net rings
+ */
+#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn)                                    \
+    (((_mfn) < (1024*1024)) &&                                            \
+     (((live_mfn_to_pfn_table[_mfn] < nr_pfns) &&                         \
+       (live_pfn_to_mfn_table[live_mfn_to_pfn_table[_mfn]] == (_mfn))) || \
+      ((live_mfn_to_pfn_table[_mfn] >= 0x80000000) &&                     \
+       (live_mfn_to_pfn_table[_mfn] <= 0x80000003)) ||                    \
+      (live_pfn_to_mfn_table[live_mfn_to_pfn_table[_mfn]] == 0x80000004)))
+     
+/* Returns TRUE if MFN is successfully converted to a PFN. */
+#define translate_mfn_to_pfn(_pmfn)            \
+({                                             \
+    unsigned long mfn = *(_pmfn);              \
+    int _res = 1;                              \
+    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )      \
+        _res = 0;                              \
+    else                                       \
+        *(_pmfn) = live_mfn_to_pfn_table[mfn]; \
+    _res;                                      \
+})
+
+static inline int test_bit ( int nr, volatile void * addr)
+{
+    return (((unsigned long*)addr)[nr/(sizeof(unsigned long)*8)] >> 
+            (nr % (sizeof(unsigned long)*8))) & 1;
+}
+
+static inline void clear_bit ( int nr, volatile void * addr)
+{
+    ((unsigned long*)addr)[nr/(sizeof(unsigned long)*8)] &= 
+        ~(1 << (nr % (sizeof(unsigned long)*8) ) );
+}
+
+static inline void set_bit ( int nr, volatile void * addr)
+{
+    ((unsigned long*)addr)[nr/(sizeof(unsigned long)*8)] |= 
+        (1 << (nr % (sizeof(unsigned long)*8) ) );
+}
+
+/* Returns the hamming weight (i.e. the number of bits set) in a N-bit word */
+static inline unsigned int hweight32(unsigned int w)
+{
+    unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
+    res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+    res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
+    res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
+    return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
+}
+
+static inline int count_bits ( int nr, volatile void *addr)
+{
+    int i, count = 0;
+    unsigned long *p = (unsigned long *)addr;
+    /* We know that the array is padded to unsigned long. */
+    for(i=0;i<nr/(sizeof(unsigned long)*8);i++,p++)
+        count += hweight32( *p );
+    return count;
+}
+
+static inline int permute( int i, int nr, int order_nr  )
+{
+    /* Need a simple permutation function so that we scan pages in a
+       pseudo random order, enabling us to get a better estimate of
+       the domain's page dirtying rate as we go (there are often 
+       contiguous ranges of pfns that have similar behaviour, and we
+       want to mix them up. */
+
+    /* e.g. nr->oder 15->4 16->4 17->5 */
+    /* 512MB domain, 128k pages, order 17 */
+
+    /*
+      QPONMLKJIHGFEDCBA  
+             QPONMLKJIH  
+      GFEDCBA  
+     */
+    
+    /*
+      QPONMLKJIHGFEDCBA  
+                  EDCBA  
+             QPONM
+      LKJIHGF
+      */
+
+    do { i = ((i>>(order_nr-10)) | ( i<<10 ) ) & ((1<<order_nr)-1); }
+    while ( i >= nr ); /* this won't ever loop if nr is a power of 2 */
+
+    return i;
+}
+
+static long long tv_to_us( struct timeval *new )
+{
+    return (new->tv_sec * 1000000) + new->tv_usec;
+}
+
+static long long llgettimeofday()
+{
+    struct timeval now;
+    gettimeofday(&now, NULL);
+    return tv_to_us(&now);
+}
+
+static long long tv_delta( struct timeval *new, struct timeval *old )
+{
+    return ((new->tv_sec - old->tv_sec)*1000000 ) + 
+        (new->tv_usec - old->tv_usec);
+}
+
+static int print_stats( int xc_handle, u32 domid, 
+                        int pages_sent, xc_shadow_control_stats_t *stats,
+                        int print )
+{
+    static struct timeval wall_last;
+    static long long      d0_cpu_last;
+    static long long      d1_cpu_last;
+
+    struct timeval        wall_now;
+    long long             wall_delta;
+    long long             d0_cpu_now, d0_cpu_delta;
+    long long             d1_cpu_now, d1_cpu_delta;
+
+    gettimeofday(&wall_now, NULL);
+
+    d0_cpu_now = xc_domain_get_cpu_usage( xc_handle, 0 )/1000;
+    d1_cpu_now = xc_domain_get_cpu_usage( xc_handle, domid )/1000;
+
+    if ( (d0_cpu_now == -1) || (d1_cpu_now == -1) ) 
+        printf("ARRHHH!!\n");
+
+    wall_delta = tv_delta(&wall_now,&wall_last)/1000;
+
+    if ( wall_delta == 0 ) wall_delta = 1;
+
+    d0_cpu_delta  = (d0_cpu_now - d0_cpu_last)/1000;
+    d1_cpu_delta  = (d1_cpu_now - d1_cpu_last)/1000;
+
+    if ( print )
+        printf("delta %lldms, dom0 %d%%, target %d%%, sent %dMb/s, "
+               "dirtied %dMb/s\n",
+               wall_delta, 
+               (int)((d0_cpu_delta*100)/wall_delta),
+               (int)((d1_cpu_delta*100)/wall_delta),
+               (int)((pages_sent*PAGE_SIZE*8)/(wall_delta*1000)),
+               (int)((stats->dirty_count*PAGE_SIZE*8)/(wall_delta*1000)));
+
+    d0_cpu_last  = d0_cpu_now;
+    d1_cpu_last  = d1_cpu_now;
+    wall_last = wall_now; 
+
+    return 0;
+}
+
+/** Write the vmconfig string.
+ * It is stored as a 4-byte count 'n' followed by n bytes.
+ *
+ * @param ioctxt i/o context
+ * @return 0 on success, non-zero on error.
+ */
+static int write_vmconfig(XcIOContext *ioctxt){
+    int err = -1;
+    if(xcio_write(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))) goto exit;
+    if(xcio_write(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)) goto exit;
+    err = 0;
+  exit:
+    return err;
+}
+
+static int analysis_phase( int xc_handle, u32 domid, 
+                           int nr_pfns, unsigned long *arr )
+{
+    long long start, now;
+    xc_shadow_control_stats_t stats;
+
+    start = llgettimeofday();
+
+    while ( 0 )
+    {
+        int i;
+
+        xc_shadow_control( xc_handle, domid, 
+                           DOM0_SHADOW_CONTROL_OP_CLEAN2,
+                           arr, nr_pfns, NULL);
+        printf("#Flush\n");
+        for ( i = 0; i < 100; i++ )
+        {     
+            usleep(10000);     
+            now = llgettimeofday();
+            xc_shadow_control( xc_handle, domid, 
+                               DOM0_SHADOW_CONTROL_OP_PEEK,
+                               NULL, 0, &stats);
+
+            printf("now= %lld faults= %ld dirty= %ld dirty_net= %ld "
+                   "dirty_block= %ld\n", 
+                   ((now-start)+500)/1000, 
+                   stats.fault_count, stats.dirty_count,
+                   stats.dirty_net_count, stats.dirty_block_count);
+        }
+    }
+
+    return -1;
+}
+
+int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
+{
+    dom0_op_t op;
+    int rc = 1, i, j, k, last_iter, iter = 0;
+    unsigned long mfn;
+    u32 domid = ioctxt->domain;
+    int live = (ioctxt->flags & XCFLAGS_LIVE);
+    int debug = (ioctxt->flags & XCFLAGS_DEBUG);
+    int sent_last_iter, skip_this_iter;
+
+    /* Important tuning parameters */
+    int max_iters  = 29; /* limit us to 30 times round loop */
+    int max_factor = 3;  /* never send more than 3x nr_pfns */
+
+    /* The new domain's shared-info frame number. */
+    unsigned long shared_info_frame;
+    
+    /* A copy of the CPU context of the guest. */
+    full_execution_context_t ctxt;
+
+    /* A copy of the domain's name. */
+    char name[MAX_DOMAIN_NAME];
+
+    /* A table containg the type of each PFN (/not/ MFN!). */
+    unsigned long *pfn_type = NULL;
+    unsigned long *pfn_batch = NULL;
+
+    /* A temporary mapping, and a copy, of one frame of guest memory. */
+    unsigned long page[1024];
+
+    /* A copy of the pfn-to-mfn table frame list. */
+    unsigned long *live_pfn_to_mfn_frame_list;
+    unsigned long pfn_to_mfn_frame_list[1024];
+
+    /* Live mapping of the table mapping each PFN to its current MFN. */
+    unsigned long *live_pfn_to_mfn_table = NULL;
+    /* Live mapping of system MFN to PFN table. */
+    unsigned long *live_mfn_to_pfn_table = NULL;
+    
+    /* Live mapping of shared info structure */
+    unsigned long *live_shinfo;
+
+    /* base of the region in which domain memory is mapped */
+    unsigned char *region_base = NULL;
+
+    /* A temporary mapping, and a copy, of the guest's suspend record. */
+    suspend_record_t *p_srec;
+
+    /* number of pages we're dealing with */
+    unsigned long nr_pfns;
+
+    /* power of 2 order of nr_pfns */
+    int order_nr; 
+
+    /* bitmap of pages:
+       - that should be sent this iteration (unless later marked as skip); 
+       - to skip this iteration because already dirty;
+       - to fixup by sending at the end if not already resent; */
+    unsigned long *to_send, *to_skip, *to_fix;
+    
+    xc_shadow_control_stats_t stats;
+
+    int needed_to_fix = 0;
+    int total_sent    = 0;
+    
+    if (mlock(&ctxt, sizeof(ctxt))) {
+        xcio_perror(ioctxt, "Unable to mlock ctxt");
+        return 1;
+    }
+
+    /* Ensure that the domain exists, and that it is stopped. */
+    if ( xc_domain_pause(xc_handle, domid) ){
+        xcio_perror(ioctxt, "Could not pause domain");
+        goto out;
+    }
+
+    if ( xc_domain_getfullinfo( xc_handle, domid, &op, &ctxt) )
+    {
+        xcio_error(ioctxt, "Could not get full domain info");
+        goto out;
+    }
+    memcpy(name, op.u.getdomaininfo.name, sizeof(name));
+    shared_info_frame = op.u.getdomaininfo.shared_info_frame;
+
+    /* A cheesy test to see whether the domain contains valid state. */
+    if ( ctxt.pt_base == 0 ){
+        xcio_error(ioctxt, "Domain is not in a valid Linux guest OS state");
+        goto out;
+    }
+
+    /* Map the suspend-record MFN to pin it. The page must be owned by 
+       domid for this to succeed. */
+    p_srec = mfn_mapper_map_single(xc_handle, domid,
+                                   sizeof(*p_srec), PROT_READ, 
+                                   ctxt.cpu_ctxt.esi);
+    if (!p_srec){
+        xcio_error(ioctxt, "Couldn't map state record");
+        goto out;
+    }
+
+    nr_pfns = p_srec->nr_pfns;
+
+    /* cheesy sanity check */
+    if ( nr_pfns > 1024*1024 ){
+        xcio_error(ioctxt, "Invalid state record -- pfn count out of range: %lu", nr_pfns);
+        goto out;
+    }
+
+    /* the pfn_to_mfn_frame_list fits in a single page */
+    live_pfn_to_mfn_frame_list = 
+        mfn_mapper_map_single(xc_handle, domid, 
+                              PAGE_SIZE, PROT_READ, 
+                              p_srec->pfn_to_mfn_frame_list );
+
+    if (!live_pfn_to_mfn_frame_list){
+        xcio_error(ioctxt, "Couldn't map pfn_to_mfn_frame_list");
+        goto out;
+    }
+
+    /* Track the mfn_to_pfn table down from the domains PT */
+    {
+        unsigned long *pgd;
+        unsigned long mfn_to_pfn_table_start_mfn;
+
+        pgd = mfn_mapper_map_single(xc_handle, domid, 
+                                    PAGE_SIZE, PROT_READ, 
+                                    ctxt.pt_base>>PAGE_SHIFT);
+
+        mfn_to_pfn_table_start_mfn = 
+            pgd[HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT]>>PAGE_SHIFT;
+
+        live_mfn_to_pfn_table = 
+            mfn_mapper_map_single(xc_handle, ~0UL, 
+                                  PAGE_SIZE*1024, PROT_READ, 
+                                  mfn_to_pfn_table_start_mfn );
+    }
+
+    /* Map all the frames of the pfn->mfn table. For migrate to succeed, 
+       the guest must not change which frames are used for this purpose. 
+       (its not clear why it would want to change them, and we'll be OK
+       from a safety POV anyhow. */
+
+    live_pfn_to_mfn_table = mfn_mapper_map_batch(xc_handle, domid, 
+                                                 PROT_READ,
+                                                 live_pfn_to_mfn_frame_list,
+                                                 (nr_pfns+1023)/1024 );  
+    if( !live_pfn_to_mfn_table ){
+        xcio_perror(ioctxt, "Couldn't map pfn_to_mfn table");
+        goto out;
+    }
+
+
+    /* Canonicalise the pfn-to-mfn table frame-number list. */
+    memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE );
+    for ( i = 0; i < nr_pfns; i += 1024 ){
+        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) ){
+            xcio_error(ioctxt, "Frame # in pfn-to-mfn frame list is not in pseudophys");
+            goto out;
+        }
+    }
+
+    /* At this point, we can start the domain again if we're doing a
+       live suspend */
+
+    if( live ){ 
+        if ( xc_shadow_control( xc_handle, domid, 
+                                DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY,
+                                NULL, 0, NULL ) < 0 ) {
+            xcio_error(ioctxt, "Couldn't enable shadow mode");
+            goto out;
+        }
+
+        if ( xc_domain_unpause(xc_handle, domid) < 0 ){
+            xcio_error(ioctxt, "Couldn't unpause domain");
+            goto out;
+        }
+
+        last_iter = 0;
+        sent_last_iter = 1<<20; /* 4GB of pages */
+    } else{
+        last_iter = 1;
+    }
+
+    /* calculate the power of 2 order of nr_pfns, e.g.
+       15->4 16->4 17->5 */
+    for( i=nr_pfns-1, order_nr=0; i ; i>>=1, order_nr++ );
+
+    /* Setup to_send bitmap */
+    {
+        int sz = (nr_pfns/8) + 8; /* includes slop at end of array */
+        to_send = malloc( sz );
+        to_fix  = calloc( 1, sz );
+        to_skip = malloc( sz );
+
+        if (!to_send || !to_fix || !to_skip){
+            xcio_error(ioctxt, "Couldn't allocate to_send array");
+            goto out;
+        }
+
+        memset( to_send, 0xff, sz );
+
+        if ( mlock( to_send, sz ) ){
+            xcio_perror(ioctxt, "Unable to mlock to_send");
+            return 1;
+        }
+
+        /* (to fix is local only) */
+
+        if ( mlock( to_skip, sz ) ){
+            xcio_perror(ioctxt, "Unable to mlock to_skip");
+            return 1;
+        }
+
+    }
+
+    analysis_phase( xc_handle, domid, nr_pfns, to_skip );
+
+    /* We want zeroed memory so use calloc rather than malloc. */
+    pfn_type = calloc(BATCH_SIZE, sizeof(unsigned long));
+    pfn_batch = calloc(BATCH_SIZE, sizeof(unsigned long));
+
+    if ( (pfn_type == NULL) || (pfn_batch == NULL) ){
+        errno = ENOMEM;
+        goto out;
+    }
+
+    if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) ){
+        xcio_error(ioctxt, "Unable to mlock");
+        goto out;
+    }
+
+
+    /*
+     * Quick belt and braces sanity check.
+     */
+#if DEBUG
+    for ( i = 0; i < nr_pfns; i++ ){
+        mfn = live_pfn_to_mfn_table[i];
+
+        if( (live_mfn_to_pfn_table[mfn] != i) && (mfn != 0x80000004) )
+            printf("i=0x%x mfn=%x live_mfn_to_pfn_table=%x\n",
+                   i,mfn,live_mfn_to_pfn_table[mfn]);
+    }
+#endif
+
+    /* Map the shared info frame */
+    live_shinfo = mfn_mapper_map_single(xc_handle, domid,
+                                        PAGE_SIZE, PROT_READ,
+                                        shared_info_frame);
+
+    if (!live_shinfo){
+        xcio_error(ioctxt, "Couldn't map live_shinfo");
+        goto out;
+    }
+
+    /* Start writing out the saved-domain record. */
+
+    if ( xcio_write(ioctxt, "LinuxGuestRecord",    16) ||
+         xcio_write(ioctxt, name,                  sizeof(name)) ||
+         xcio_write(ioctxt, &nr_pfns,              sizeof(unsigned long)) ||
+         xcio_write(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ){
+        xcio_error(ioctxt, "Error writing header");
+        goto out;
+    }
+    if(write_vmconfig(ioctxt)){
+        xcio_error(ioctxt, "Error writing vmconfig");
+        goto out;
+    }
+
+    print_stats( xc_handle, domid, 0, &stats, 0 );
+
+    /* Now write out each data page, canonicalising page tables as we go... */
+    
+    while(1){
+        unsigned int prev_pc, sent_this_iter, N, batch;
+
+        iter++;
+        sent_this_iter = 0;
+        skip_this_iter = 0;
+        prev_pc = 0;
+        N=0;
+
+        xcio_info(ioctxt, "Saving memory pages: iter %d   0%%", iter);
+
+        while( N < nr_pfns ){
+            unsigned int this_pc = (N * 100) / nr_pfns;
+
+            if ( (this_pc - prev_pc) >= 5 ){
+                xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc);
+                prev_pc = this_pc;
+            }
+
+            /* slightly wasteful to peek the whole array evey time, 
+               but this is fast enough for the moment. */
+
+            if ( !last_iter && 
+                 xc_shadow_control(xc_handle, domid, 
+                                   DOM0_SHADOW_CONTROL_OP_PEEK,
+                                   to_skip, nr_pfns, NULL) != nr_pfns ) {
+                xcio_error(ioctxt, "Error peeking shadow bitmap");
+                goto out;
+            }
+     
+
+            /* load pfn_type[] with the mfn of all the pages we're doing in
+               this batch. */
+
+            for ( batch = 0; batch < BATCH_SIZE && N < nr_pfns ; N++ )
+            {
+                int n = permute(N, nr_pfns, order_nr );
+
+                if ( 0 && debug ) {
+                    fprintf(stderr,"%d pfn= %08lx mfn= %08lx %d  "
+                            " [mfn]= %08lx\n",
+                            iter, (unsigned long)n, live_pfn_to_mfn_table[n],
+                            test_bit(n,to_send),
+                            live_mfn_to_pfn_table[live_pfn_to_mfn_table[n]&
+                                                 0xFFFFF]);
+                }
+
+                if ( !last_iter && 
+                     test_bit(n, to_send) && 
+                     test_bit(n, to_skip) ) {
+                    skip_this_iter++; /* stats keeping */
+                }
+
+                if ( !((test_bit(n, to_send) && !test_bit(n, to_skip)) ||
+                       (test_bit(n, to_send) && last_iter) ||
+                       (test_bit(n, to_fix)  && last_iter)) ) {
+                    continue;
+                }
+
+                /* we get here if:
+                   1. page is marked to_send & hasn't already been re-dirtied
+                   2. (ignore to_skip in last iteration)
+                   3. add in pages that still need fixup (net bufs)
+                */
+  
+                pfn_batch[batch] = n;
+                pfn_type[batch] = live_pfn_to_mfn_table[n];
+
+                if( pfn_type[batch] == 0x80000004 ){
+                    /* not currently in pusedo-physical map -- set bit
+                       in to_fix that we must send this page in last_iter
+                       unless its sent sooner anyhow */
+
+                    set_bit( n, to_fix );
+                    if( iter>1 )
+                        DDPRINTF("netbuf race: iter %d, pfn %lx. mfn %lx\n",
+                                 iter,n,pfn_type[batch]);
+                    continue;
+                }
+
+                if ( last_iter && 
+                     test_bit(n, to_fix) && 
+                     !test_bit(n, to_send) )
+                {
+                    needed_to_fix++;
+                    DPRINTF("Fix! iter %d, pfn %lx. mfn %lx\n",
+                            iter,n,pfn_type[batch]);
+                }
+
+                clear_bit(n, to_fix); 
+
+                batch++;
+            }
+     
+            DDPRINTF("batch %d:%d (n=%d)\n", iter, batch, n);
+
+            if ( batch == 0 )
+                goto skip; /* vanishingly unlikely... */
+      
+            if ( (region_base = mfn_mapper_map_batch(xc_handle, domid, 
+                                                     PROT_READ,
+                                                     pfn_type,
+                                                     batch)) == 0 ){
+                xcio_perror(ioctxt, "map batch failed");
+                goto out;
+            }
+     
+            if ( get_pfn_type_batch(xc_handle, domid, batch, pfn_type) ){
+                xcio_error(ioctxt, "get_pfn_type_batch failed");
+                goto out;
+            }
+     
+            for ( j = 0; j < batch; j++ ){
+                if ( (pfn_type[j] & LTAB_MASK) == XTAB ){
+                    DDPRINTF("type fail: page %i mfn %08lx\n",j,pfn_type[j]);
+                    continue;
+                }
+  
+                if ( 0 && debug )
+                    fprintf(stderr, "%d pfn= %08lx mfn= %08lx [mfn]= %08lx"
+                            " sum= %08lx\n",
+                            iter, 
+                            (pfn_type[j] & LTAB_MASK) | pfn_batch[j],
+                            pfn_type[j],
+                            live_mfn_to_pfn_table[pfn_type[j]&(~LTAB_MASK)],
+                            csum_page(region_base + (PAGE_SIZE*j)));
+
+                /* canonicalise mfn->pfn */
+                pfn_type[j] = (pfn_type[j] & LTAB_MASK) | pfn_batch[j];
+            }
+
+            if ( xcio_write(ioctxt, &batch, sizeof(int) ) ){
+                xcio_error(ioctxt, "Error when writing to state file (2)");
+                goto out;
+            }
+
+            if ( xcio_write(ioctxt, pfn_type, sizeof(unsigned long)*j ) ){
+                xcio_error(ioctxt, "Error when writing to state file (3)");
+                goto out;
+            }
+     
+            /* entering this loop, pfn_type is now in pfns (Not mfns) */
+            for( j = 0; j < batch; j++ ){
+                /* write out pages in batch */
+                if( (pfn_type[j] & LTAB_MASK) == XTAB){
+                    DDPRINTF("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]);
+                    continue;
+                }
+  
+                if ( ((pfn_type[j] & LTAB_MASK) == L1TAB) || 
+                     ((pfn_type[j] & LTAB_MASK) == L2TAB) ){
+                    memcpy(page, region_base + (PAGE_SIZE*j), PAGE_SIZE);
+      
+                    for ( k = 0; 
+                          k < (((pfn_type[j] & LTAB_MASK) == L2TAB) ? 
+                               (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) :
+                               1024); 
+                          k++ ){
+                        unsigned long pfn;
+
+                        if ( !(page[k] & _PAGE_PRESENT) )
+                            continue;
+                        
+                        mfn = page[k] >> PAGE_SHIFT;      
+                        pfn = live_mfn_to_pfn_table[mfn];
+
+                        if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
+                        {
+                            /* I don't think this should ever happen */
+                            printf("FNI %d : [%08lx,%d] pte=%08lx, "
+                                   "mfn=%08lx, pfn=%08lx [mfn]=%08lx\n",
+                                   j, pfn_type[j], k,
+                                   page[k], mfn, live_mfn_to_pfn_table[mfn],
+                                   (live_mfn_to_pfn_table[mfn]<nr_pfns)? 
+                                   live_pfn_to_mfn_table[
+                                       live_mfn_to_pfn_table[mfn]] : 
+                                   0xdeadbeef);
+
+                            pfn = 0; /* be suspicious */
+                        }
+
+                        page[k] &= PAGE_SIZE - 1;
+                        page[k] |= pfn << PAGE_SHIFT;
+   
+#if 0
+                        printf("L%d i=%d pfn=%d mfn=%d k=%d pte=%08lx "
+                               "xpfn=%d\n",
+                               pfn_type[j]>>28,
+                               j,i,mfn,k,page[k],page[k]>>PAGE_SHIFT);
+#endif     
+   
+                    } /* end of page table rewrite for loop */
+      
+                    if ( xcio_write(ioctxt, page, PAGE_SIZE) ){
+                        xcio_error(ioctxt, "Error when writing to state file (4)");
+                        goto out;
+                    }
+      
+                }  /* end of it's a PT page */ else {  /* normal page */
+
+                    if ( xcio_write(ioctxt, region_base + (PAGE_SIZE*j), 
+                                     PAGE_SIZE) ){
+                        xcio_error(ioctxt, "Error when writing to state file (5)");
+                        goto out;
+                    }
+                }
+            } /* end of the write out for this batch */
+     
+            sent_this_iter += batch;
+
+        } /* end of this while loop for this iteration */
+
+        munmap(region_base, batch*PAGE_SIZE);
+
+    skip: 
+
+        total_sent += sent_this_iter;
+
+        xcio_info(ioctxt, "\r %d: sent %d, skipped %d, ", 
+                       iter, sent_this_iter, skip_this_iter );
+
+        if ( last_iter ) {
+            print_stats( xc_handle, domid, sent_this_iter, &stats, 1);
+
+            xcio_info(ioctxt, "Total pages sent= %d (%.2fx)\n", 
+                           total_sent, ((float)total_sent)/nr_pfns );
+            xcio_info(ioctxt, "(of which %d were fixups)\n", needed_to_fix  );
+        }       
+
+        if (last_iter && debug){
+            int minusone = -1;
+            memset( to_send, 0xff, (nr_pfns+8)/8 );
+            debug = 0;
+            printf("Entering debug resend-all mode\n");
+    
+            /* send "-1" to put receiver into debug mode */
+            if ( xcio_write(ioctxt, &minusone, sizeof(int)) )
+            {
+                xcio_error(ioctxt, "Error when writing to state file (6)");
+                goto out;
+            }
+
+            continue;
+        }
+
+        if ( last_iter ) break;
+
+        if ( live )
+        {
+            if ( 
+                /* ( sent_this_iter > (sent_last_iter * 0.95) ) || */
+                (iter >= max_iters) || 
+                (sent_this_iter+skip_this_iter < 50) || 
+                (total_sent > nr_pfns*max_factor) )
+            {
+                DPRINTF("Start last iteration\n");
+                last_iter = 1;
+
+                xc_domain_pause( xc_handle, domid );
+            } 
+
+            if ( xc_shadow_control( xc_handle, domid, 
+                                    DOM0_SHADOW_CONTROL_OP_CLEAN2,
+                                    to_send, nr_pfns, &stats ) != nr_pfns ) 
+            {
+                xcio_error(ioctxt, "Error flushing shadow PT");
+                goto out;
+            }
+
+            sent_last_iter = sent_this_iter;
+
+            print_stats( xc_handle, domid, sent_this_iter, &stats, 1);
+     
+        }
+
+
+    } /* end of while 1 */
+
+    DPRINTF("All memory is saved\n");
+
+    /* Success! */
+    rc = 0;
+    
+    /* Zero terminate */
+    if ( xcio_write(ioctxt, &rc, sizeof(int)) )
+    {
+        xcio_error(ioctxt, "Error when writing to state file (6)");
+        goto out;
+    }
+
+    /* Get the final execution context */
+    if ( xc_domain_getfullinfo( xc_handle, domid, &op, &ctxt) )
+    {
+        xcio_perror(ioctxt, "Could not get full domain info");
+        goto out;
+    }
+
+    /* Canonicalise the suspend-record frame number. */
+    if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) ){
+        xcio_error(ioctxt, "State record is not in range of pseudophys map");
+        goto out;
+    }
+
+    /* Canonicalise each GDT frame number. */
+    for ( i = 0; i < ctxt.gdt_ents; i += 512 ) {
+        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) {
+            xcio_error(ioctxt, "GDT frame is not in range of pseudophys map");
+            goto out;
+        }
+    }
+
+    /* Canonicalise the page table base pointer. */
+    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) ) {
+        xcio_error(ioctxt, "PT base is not in range of pseudophys map");
+        goto out;
+    }
+    ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] <<
+        PAGE_SHIFT;
+
+    if ( xcio_write(ioctxt, &ctxt,       sizeof(ctxt)) ||
+         xcio_write(ioctxt, live_shinfo, PAGE_SIZE) ) {
+        xcio_error(ioctxt, "Error when writing to state file (1)");
+        goto out;
+    }
+    munmap(live_shinfo, PAGE_SIZE);
+
+ out:
+    if ( pfn_type != NULL ) free(pfn_type);
+    DPRINTF("Save exit rc=%d\n",rc);
+    return !!rc;
+
+}
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
new file mode 100644 (file)
index 0000000..0019ffe
--- /dev/null
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * xc_misc.c
+ * 
+ * Miscellaneous control interface functions.
+ */
+
+#include "xc_private.h"
+
+int xc_interface_open(void)
+{
+    int fd = open("/proc/xen/privcmd", O_RDWR);
+    if ( fd == -1 )
+        PERROR("Could not obtain handle on privileged command interface");
+    return fd;
+}
+
+int xc_interface_close(int xc_handle)
+{
+    return close(xc_handle);
+}
+
+
+#define CONSOLE_RING_CLEAR 1
+
+int xc_readconsolering(int xc_handle,
+                       char *str, 
+                       unsigned int max_chars, 
+                       int clear)
+{
+    int ret;
+    dom0_op_t op;
+
+    op.cmd = DOM0_READCONSOLE;
+    op.u.readconsole.str = (unsigned long)str;
+    op.u.readconsole.count = max_chars;
+    op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0;
+
+    if ( (ret = mlock(str, max_chars)) != 0 )
+        return ret;
+
+    if ( (ret = do_dom0_op(xc_handle, &op)) >= 0 )
+        str[ret] = '\0';
+
+    (void)munlock(str, max_chars);
+
+    return ret;
+}    
+
+
+int xc_physinfo(int xc_handle,
+                xc_physinfo_t *put_info)
+{
+    int ret;
+    dom0_op_t op;
+    dom0_physinfo_t *got_info = &op.u.physinfo;
+    
+    op.cmd = DOM0_PHYSINFO;
+    op.interface_version = DOM0_INTERFACE_VERSION;
+
+    if((ret = do_dom0_op(xc_handle, &op))) return ret;
+
+    put_info->ht_per_core = got_info->ht_per_core;
+    put_info->cores       = got_info->cores;
+    put_info->total_pages = got_info->total_pages;
+    put_info->free_pages  = got_info->free_pages;
+    put_info->cpu_khz     = got_info->cpu_khz;
+
+    return 0;
+}
+
+
+int xc_sched_id(int xc_handle,
+                int *sched_id)
+{
+    int ret;
+    dom0_op_t op;
+    
+    op.cmd = DOM0_SCHED_ID;
+    op.interface_version = DOM0_INTERFACE_VERSION;
+    
+    if((ret = do_dom0_op(xc_handle, &op))) return ret;
+    
+    *sched_id = op.u.sched_id.sched_id;
+    
+    return 0;
+}
+
diff --git a/tools/libxc/xc_netbsd_build.c b/tools/libxc/xc_netbsd_build.c
new file mode 100644 (file)
index 0000000..04a47b5
--- /dev/null
@@ -0,0 +1,705 @@
+/******************************************************************************
+ * xc_netbsd_build.c
+ */
+
+#include "xc_private.h"
+#define ELFSIZE 32  /* XXX */
+#include "xc_elf.h"
+#include <zlib.h>
+
+#ifdef DEBUG
+#define DPRINTF(x) printf x
+#else
+#define DPRINTF(x)
+#endif
+
+static int loadelfimage(gzFile, int, unsigned long *, unsigned long,
+                        unsigned long *, unsigned long *,
+                        unsigned long *, unsigned long *);
+
+#define ELFROUND (ELFSIZE / 8)
+
+#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
+#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
+
+static long get_tot_pages(int xc_handle, u32 domid)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_GETDOMAININFO;
+    op.u.getdomaininfo.domain = (domid_t)domid;
+    op.u.getdomaininfo.ctxt = NULL;
+    return (do_dom0_op(xc_handle, &op) < 0) ? 
+        -1 : op.u.getdomaininfo.tot_pages;
+}
+
+static int get_pfn_list(int xc_handle,
+                        u32 domid, 
+                        unsigned long *pfn_buf, 
+                        unsigned long max_pfns)
+{
+    dom0_op_t op;
+    int ret;
+    op.cmd = DOM0_GETMEMLIST;
+    op.u.getmemlist.domain   = (domid_t)domid;
+    op.u.getmemlist.max_pfns = max_pfns;
+    op.u.getmemlist.buffer   = pfn_buf;
+
+    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
+        return -1;
+
+    ret = do_dom0_op(xc_handle, &op);
+
+    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
+
+    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
+}
+
+static int setup_guestos(int xc_handle,
+                         u32 dom, 
+                         gzFile kernel_gfd, 
+                         unsigned long tot_pages,
+                         unsigned long *virt_startinfo_addr, 
+                         unsigned long *virt_load_addr, 
+                         full_execution_context_t *ctxt,
+                         const char *cmdline,
+                         unsigned long shared_info_frame,
+                         unsigned int control_evtchn)
+{
+    l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
+    l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
+    unsigned long *page_array = NULL;
+    int alloc_index, num_pt_pages;
+    unsigned long l2tab;
+    unsigned long l1tab;
+    unsigned long count, pt_start;
+    unsigned long symtab_addr = 0, symtab_len = 0;
+    extended_start_info_t *start_info;
+    shared_info_t *shared_info;
+    unsigned long ksize;
+    mmu_t *mmu = NULL;
+    int pm_handle, i;
+
+    if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 )
+        goto error_out;
+
+    if ( (page_array = malloc(tot_pages * sizeof(unsigned long))) == NULL )
+    {
+        PERROR("Could not allocate memory");
+        goto error_out;
+    }
+
+    if ( get_pfn_list(xc_handle, dom, page_array, tot_pages) != tot_pages )
+    {
+        PERROR("Could not get the page frame list");
+        goto error_out;
+    }
+
+    if (loadelfimage(kernel_gfd, pm_handle, page_array, tot_pages,
+                     virt_load_addr, &ksize, &symtab_addr, &symtab_len))
+        goto error_out;
+
+    /* ksize is kernel-image size rounded up to a page boundary. */
+
+    alloc_index = tot_pages - 1;
+
+    /* Count bottom-level PTs, rounding up. */
+    num_pt_pages = (l1_table_offset(*virt_load_addr) + tot_pages + 1023)
+        / 1024;
+
+    /* We must also count the page directory. */
+    num_pt_pages++;
+
+    /* Index of first PT page. */
+    pt_start = tot_pages - num_pt_pages;
+
+    /*
+     * First allocate page for page dir. Allocation goes backwards from the end
+     * of the allocated physical address space.
+     */
+    l2tab = page_array[alloc_index] << PAGE_SHIFT;
+    alloc_index--;
+    ctxt->pt_base = l2tab;
+    
+    if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL )
+        goto error_out;
+    
+    /* Initialise the page tables. */
+    if ( (vl2tab = map_pfn_writeable(pm_handle, l2tab >> PAGE_SHIFT)) == NULL )
+        goto error_out;
+    memset(vl2tab, 0, PAGE_SIZE);
+    vl2e = &vl2tab[l2_table_offset(*virt_load_addr)];
+    for ( count = 0; count < tot_pages; count++ )
+    {
+        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
+        {
+            l1tab = page_array[alloc_index--] << PAGE_SHIFT;
+            if ( vl1tab != NULL )
+                unmap_pfn(pm_handle, vl1tab);
+            if ( (vl1tab = map_pfn_writeable(pm_handle,
+                                             l1tab >> PAGE_SHIFT)) == NULL )
+                goto error_out;
+            memset(vl1tab, 0, PAGE_SIZE);
+            vl1e = &vl1tab[l1_table_offset(*virt_load_addr + 
+                                           (count<<PAGE_SHIFT))];
+            *vl2e++ = l1tab | L2_PROT;
+        }
+
+        *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
+        if ( count >= pt_start )
+            *vl1e &= ~_PAGE_RW;
+        vl1e++;
+
+        if ( add_mmu_update(xc_handle, mmu,
+                            (page_array[count] << PAGE_SHIFT) | 
+                            MMU_MACHPHYS_UPDATE, count) )
+            goto error_out;
+    }
+    unmap_pfn(pm_handle, vl1tab);
+    unmap_pfn(pm_handle, vl2tab);
+
+    /*
+     * Pin down l2tab addr as page dir page - causes hypervisor to provide
+     * correct protection for the page
+     */ 
+    if ( add_mmu_update(xc_handle, mmu,
+                        l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L2_TABLE) )
+        goto error_out;
+
+    *virt_startinfo_addr =
+        *virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
+
+    start_info = map_pfn_writeable(pm_handle, page_array[alloc_index-1]);
+    memset(start_info, 0, sizeof(*start_info));
+    start_info->pt_base     = *virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
+    start_info->mod_start   = symtab_addr;
+    start_info->mod_len     = symtab_len;
+    start_info->nr_pages    = tot_pages;
+    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
+    start_info->flags       = 0;
+    start_info->domain_controller_evtchn = control_evtchn;
+    strncpy(start_info->cmd_line, cmdline, MAX_CMDLINE);
+    start_info->cmd_line[MAX_CMDLINE-1] = '\0';
+    unmap_pfn(pm_handle, start_info);
+
+    /* shared_info page starts its life empty. */
+    shared_info = map_pfn_writeable(pm_handle, shared_info_frame);
+    memset(shared_info, 0, PAGE_SIZE);
+    /* Mask all upcalls... */
+    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
+        shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
+    unmap_pfn(pm_handle, shared_info);
+
+    /* Send the page update requests down to the hypervisor. */
+    if ( finish_mmu_updates(xc_handle, mmu) )
+        goto error_out;
+
+    free(mmu);
+    (void)close_pfn_mapper(pm_handle);
+    free(page_array);
+    return 0;
+
+ error_out:
+    if ( mmu != NULL )
+        free(mmu);
+    if ( pm_handle >= 0 )
+        (void)close_pfn_mapper(pm_handle);
+    if ( page_array == NULL )
+        free(page_array);
+    return -1;
+}
+
+int xc_netbsd_build(int xc_handle,
+                    u32 domid,
+                    const char *image_name,
+                    const char *cmdline,
+                    unsigned int control_evtchn)
+{
+    dom0_op_t launch_op, op;
+    unsigned long load_addr;
+    long tot_pages;
+    int kernel_fd = -1;
+    gzFile kernel_gfd = NULL;
+    int rc, i;
+    full_execution_context_t st_ctxt, *ctxt = &st_ctxt;
+    unsigned long virt_startinfo_addr;
+
+    if ( (tot_pages = get_tot_pages(xc_handle, domid)) < 0 )
+    {
+        PERROR("Could not find total pages for domain");
+        return 1;
+    }
+
+    kernel_fd = open(image_name, O_RDONLY);
+    if ( kernel_fd < 0 )
+    {
+        PERROR("Could not open kernel image");
+        return 1;
+    }
+
+    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
+    {
+        PERROR("Could not allocate decompression state for state file");
+        close(kernel_fd);
+        return 1;
+    }
+
+    if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
+    {   
+        PERROR("Unable to mlock ctxt");
+        return 1;
+    }
+
+    op.cmd = DOM0_GETDOMAININFO;
+    op.u.getdomaininfo.domain = (domid_t)domid;
+    op.u.getdomaininfo.ctxt = ctxt;
+    if ( (do_dom0_op(xc_handle, &op) < 0) || 
+         ((u32)op.u.getdomaininfo.domain != domid) )
+    {
+        PERROR("Could not get info on domain");
+        goto error_out;
+    }
+    if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ||
+         (op.u.getdomaininfo.ctxt->pt_base != 0) )
+    {
+        ERROR("Domain is already constructed");
+        goto error_out;
+    }
+
+    if ( setup_guestos(xc_handle, domid, kernel_gfd, tot_pages,
+                       &virt_startinfo_addr,
+                       &load_addr, &st_ctxt, cmdline,
+                       op.u.getdomaininfo.shared_info_frame,
+                       control_evtchn) < 0 )
+    {
+        ERROR("Error constructing guest OS");
+        goto error_out;
+    }
+
+    if ( kernel_fd >= 0 )
+        close(kernel_fd);
+    if( kernel_gfd )
+        gzclose(kernel_gfd);
+
+    ctxt->flags = 0;
+
+    /*
+     * Initial register values:
+     *  DS,ES,FS,GS = FLAT_GUESTOS_DS
+     *       CS:EIP = FLAT_GUESTOS_CS:start_pc
+     *       SS:ESP = FLAT_GUESTOS_DS:start_stack
+     *          ESI = start_info
+     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
+     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
+     */
+    ctxt->cpu_ctxt.ds = FLAT_GUESTOS_DS;
+    ctxt->cpu_ctxt.es = FLAT_GUESTOS_DS;
+    ctxt->cpu_ctxt.fs = FLAT_GUESTOS_DS;
+    ctxt->cpu_ctxt.gs = FLAT_GUESTOS_DS;
+    ctxt->cpu_ctxt.ss = FLAT_GUESTOS_DS;
+    ctxt->cpu_ctxt.cs = FLAT_GUESTOS_CS;
+    ctxt->cpu_ctxt.eip = load_addr;
+    ctxt->cpu_ctxt.esp = virt_startinfo_addr;
+    ctxt->cpu_ctxt.esi = virt_startinfo_addr;
+    ctxt->cpu_ctxt.eflags = (1<<9) | (1<<2);
+
+    /* FPU is set up to default initial state. */
+    memset(ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
+
+    /* Virtual IDT is empty at start-of-day. */
+    for ( i = 0; i < 256; i++ )
+    {
+        ctxt->trap_ctxt[i].vector = i;
+        ctxt->trap_ctxt[i].cs     = FLAT_GUESTOS_CS;
+    }
+    ctxt->fast_trap_idx = 0;
+
+    /* No LDT. */
+    ctxt->ldt_ents = 0;
+    
+    /* Use the default Xen-provided GDT. */
+    ctxt->gdt_ents = 0;
+
+    /* Ring 1 stack is the initial stack. */
+    ctxt->guestos_ss  = FLAT_GUESTOS_DS;
+    ctxt->guestos_esp = virt_startinfo_addr;
+
+    /* No debugging. */
+    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
+
+    /* No callback handlers. */
+    ctxt->event_callback_cs     = FLAT_GUESTOS_CS;
+    ctxt->event_callback_eip    = 0;
+    ctxt->failsafe_callback_cs  = FLAT_GUESTOS_CS;
+    ctxt->failsafe_callback_eip = 0;
+
+    memset( &launch_op, 0, sizeof(launch_op) );
+
+    launch_op.u.builddomain.domain   = (domid_t)domid;
+    launch_op.u.builddomain.ctxt = ctxt;
+    launch_op.cmd = DOM0_BUILDDOMAIN;
+    rc = do_dom0_op(xc_handle, &launch_op);
+    
+    return rc;
+
+ error_out:
+    if ( kernel_fd >= 0 )
+        close(kernel_fd);
+    if( kernel_gfd )
+        gzclose(kernel_gfd);
+
+    return -1;
+}
+
+#define MYSEEK_BUFSIZE 1024
+static off_t
+myseek(gzFile gfd, off_t offset, int whence)
+{
+    unsigned char tmp[MYSEEK_BUFSIZE];
+    int c;
+
+    if ( offset < 0 )
+    {
+        ERROR("seek back not supported");
+        return -1;
+    }
+
+    while ( offset != 0 )
+    {
+        c = offset;
+        if ( c > MYSEEK_BUFSIZE )
+            c = MYSEEK_BUFSIZE;
+        if ( gzread(gfd, tmp, c) != c )
+        {
+            PERROR("Error seeking in image.");
+            return -1;
+        }
+        offset -= c;
+    }
+
+    return 0;   /* XXX */
+}
+
+/* 
+ * NetBSD memory layout:
+ *
+ * ---------------- *virt_load_addr = ehdr.e_entry (0xc0100000)
+ * | kernel text  |
+ * |              |
+ * ----------------
+ * | kernel data  |
+ * |              |
+ * ----------------
+ * | kernel bss   |
+ * |              |
+ * ---------------- *symtab_addr
+ * | symtab size  |   = *symtab_len
+ * ----------------
+ * | elf header   |   offsets to symbol sections mangled to be relative
+ * |              |   to headers location
+ * ----------------
+ * | sym section  |
+ * | headers      |
+ * ----------------
+ * | sym sections |
+ * |              |
+ * ---------------- *symtab_addr + *symtab_len
+ * | padding      |
+ * ---------------- ehdr.e_entry + *ksize << PAGE_SHIFT
+ */
+
+#define IS_TEXT(p) (p.p_flags & PF_X)
+#define IS_DATA(p) (p.p_flags & PF_W)
+#define IS_BSS(p) (p.p_filesz < p.p_memsz)
+
+static int
+loadelfimage(gzFile kernel_gfd, int pm_handle, unsigned long *page_array,
+             unsigned long tot_pages, unsigned long *virt_load_addr,
+             unsigned long *ksize, unsigned long *symtab_addr,
+             unsigned long *symtab_len)
+{
+    Elf_Ehdr ehdr;
+    Elf_Phdr *phdr;
+    Elf_Shdr *shdr;
+    void *vaddr;
+    char page[PAGE_SIZE], *p;
+    unsigned long iva, maxva, symva;
+    int c, curpos, h, i, ret, s;
+
+    ret = -1;
+    phdr = NULL;
+    p = NULL;
+    maxva = 0;
+
+    if ( gzread(kernel_gfd, &ehdr, sizeof(Elf_Ehdr)) != sizeof(Elf_Ehdr) )
+    {
+        PERROR("Error reading kernel image ELF header.");
+        goto out;
+    }
+    curpos = sizeof(Elf_Ehdr);
+
+    if ( !IS_ELF(ehdr) )
+    {
+        PERROR("Image does not have an ELF header.");
+        goto out;
+    }
+
+    *virt_load_addr = ehdr.e_entry;
+
+    if ( (*virt_load_addr & (PAGE_SIZE-1)) != 0 )
+    {
+        ERROR("We can only deal with page-aligned load addresses");
+        goto out;
+    }
+
+    if ( (*virt_load_addr + (tot_pages << PAGE_SHIFT)) > 
+         HYPERVISOR_VIRT_START )
+    {
+        ERROR("Cannot map all domain memory without hitting Xen space");
+        goto out;
+    }
+
+
+    phdr = malloc(ehdr.e_phnum * sizeof(Elf_Phdr));
+    if ( phdr == NULL )
+    {
+        ERROR("Cannot allocate memory for Elf_Phdrs");
+        goto out;
+    }
+
+    if ( myseek(kernel_gfd, ehdr.e_phoff - curpos, SEEK_SET) == -1 )
+    {
+        ERROR("Seek to program header failed");
+        goto out;
+    }
+    curpos = ehdr.e_phoff;
+
+    if ( gzread(kernel_gfd, phdr, ehdr.e_phnum * sizeof(Elf_Phdr)) !=
+         ehdr.e_phnum * sizeof(Elf_Phdr) )
+    {
+        PERROR("Error reading kernel image ELF program header.");
+        goto out;
+    }
+    curpos += ehdr.e_phnum * sizeof(Elf_Phdr);
+
+    /* Copy run-time 'load' segments that are writeable and/or executable. */
+    for ( h = 0; h < ehdr.e_phnum; h++ ) 
+    {
+        if ( (phdr[h].p_type != PT_LOAD) ||
+             ((phdr[h].p_flags & (PF_W|PF_X)) == 0) )
+            continue;
+
+        if ( IS_TEXT(phdr[h]) || IS_DATA(phdr[h]) )
+        {
+            if ( myseek(kernel_gfd, phdr[h].p_offset - curpos, 
+                        SEEK_SET) == -1 )
+            {
+                ERROR("Seek to section failed");
+                goto out;
+            }
+            curpos = phdr[h].p_offset;
+
+            for ( iva = phdr[h].p_vaddr;
+                  iva < phdr[h].p_vaddr + phdr[h].p_filesz; 
+                  iva += c)
+            {
+                c = PAGE_SIZE - (iva & (PAGE_SIZE - 1));
+                if (iva + c > phdr[h].p_vaddr + phdr[h].p_filesz)
+                    c = phdr[h].p_vaddr + phdr[h].p_filesz - iva;
+                if ( gzread(kernel_gfd, page, c) != c )
+                {
+                    PERROR("Error reading kernel image page.");
+                    goto out;
+                }
+                curpos += c;
+                vaddr = map_pfn_writeable(pm_handle, 
+                                          page_array[(iva - *virt_load_addr)
+                                                    >> PAGE_SHIFT]);
+                if ( vaddr == NULL )
+                {
+                    ERROR("Couldn't map guest memory");
+                    goto out;
+                }
+                DPRINTF(("copy page %p to %p, count 0x%x\n", (void *)iva,
+                         vaddr + (iva & (PAGE_SIZE - 1)), c));
+                memcpy(vaddr + (iva & (PAGE_SIZE - 1)), page, c);
+                unmap_pfn(pm_handle, vaddr);
+            }
+
+            if ( phdr[h].p_vaddr + phdr[h].p_filesz > maxva )
+                maxva = phdr[h].p_vaddr + phdr[h].p_filesz;
+        }
+
+        if ( IS_BSS(phdr[h]) )
+        {
+            /* XXX maybe clear phdr[h].p_memsz bytes from
+               phdr[h].p_vaddr + phdr[h].p_filesz ??? */
+            if (phdr[h].p_vaddr + phdr[h].p_memsz > maxva)
+                maxva = phdr[h].p_vaddr + phdr[h].p_memsz;
+            DPRINTF(("bss from %p to %p, maxva %p\n",
+                     (void *)(phdr[h].p_vaddr + phdr[h].p_filesz),
+                     (void *)(phdr[h].p_vaddr + phdr[h].p_memsz),
+                     (void *)maxva));
+        }
+    }
+
+    p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
+               ehdr.e_shnum * sizeof(Elf_Shdr));
+    if ( p == NULL )
+    {
+        ERROR("Cannot allocate memory for Elf_Shdrs");
+        goto out;
+    }
+
+    shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
+
+    if ( myseek(kernel_gfd, ehdr.e_shoff - curpos, SEEK_SET) == -1 )
+    {
+        ERROR("Seek to symbol header failed");
+        goto out;
+    }
+    curpos = ehdr.e_shoff;
+
+    if ( gzread(kernel_gfd, shdr, ehdr.e_shnum * sizeof(Elf_Shdr)) !=
+         ehdr.e_shnum * sizeof(Elf_Shdr) ) 
+    {
+        PERROR("Error reading kernel image ELF symbol header.");
+        goto out;
+    }
+    curpos += ehdr.e_shnum * sizeof(Elf_Shdr);
+
+    maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
+    symva = maxva;
+    maxva += sizeof(int);
+    *symtab_addr = maxva;
+    *symtab_len = 0;
+    maxva += sizeof(Elf_Ehdr) + ehdr.e_shnum * sizeof(Elf_Shdr);
+    maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
+
+    /* Copy kernel string / symbol tables into physical memory */
+    for ( h = 0; h < ehdr.e_shnum; h++ )
+    {
+        if ( shdr[h].sh_type == SHT_STRTAB )
+        {
+            /* Look for a strtab @i linked to symtab @h. */
+            for ( i = 0; i < ehdr.e_shnum; i++ )
+                if ( (shdr[i].sh_type == SHT_SYMTAB) &&
+                     (shdr[i].sh_link == h) )
+                    break;
+            /* Skip symtab @h if we found no corresponding strtab @i. */
+            if ( i == ehdr.e_shnum )
+            {
+                shdr[h].sh_offset = 0;
+                continue;
+            }
+        }
+
+        if ( (shdr[h].sh_type == SHT_STRTAB) ||
+             (shdr[h].sh_type == SHT_SYMTAB) )
+        {
+            if ( myseek(kernel_gfd, shdr[h].sh_offset - curpos, 
+                        SEEK_SET) == -1 )
+            {
+                ERROR("Seek to symbol section failed");
+                goto out;
+            }
+            curpos = shdr[h].sh_offset;
+
+            /* Mangled to be based on ELF header location. */
+            shdr[h].sh_offset = maxva - *symtab_addr;
+
+            DPRINTF(("copy section %d, size 0x%x\n", h, shdr[h].sh_size));
+            for ( i = 0; i < shdr[h].sh_size; i += c, maxva += c )
+            {
+                c = PAGE_SIZE - (maxva & (PAGE_SIZE - 1));
+                if ( c > (shdr[h].sh_size - i) )
+                    c = shdr[h].sh_size - i;
+                if ( gzread(kernel_gfd, page, c) != c )
+                {
+                    PERROR("Error reading kernel image page.");
+                    goto out;
+                }
+                curpos += c;
+
+                vaddr = map_pfn_writeable(pm_handle, 
+                                          page_array[(maxva - *virt_load_addr)
+                                                    >> PAGE_SHIFT]);
+                if ( vaddr == NULL )
+                {
+                    ERROR("Couldn't map guest memory");
+                    goto out;
+                }
+                DPRINTF(("copy page %p to %p, count 0x%x\n", (void *)maxva,
+                         vaddr + (maxva & (PAGE_SIZE - 1)), c));
+                memcpy(vaddr + (maxva & (PAGE_SIZE - 1)), page, c);
+                unmap_pfn(pm_handle, vaddr);
+            }
+
+            *symtab_len += shdr[h].sh_size;
+            maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
+
+        }
+        shdr[h].sh_name = 0;  /* Name is NULL. */
+    }
+
+    if ( *symtab_len == 0 ) 
+    {
+        DPRINTF(("no symbol table\n"));
+        *symtab_addr = 0;
+        ret = 0;
+        goto out;
+    }
+
+    DPRINTF(("sym header va %p from %p/%p size %x/%x\n", (void *)symva,
+             shdr, p, ehdr.e_shnum * sizeof(Elf_Shdr),
+             ehdr.e_shnum * sizeof(Elf_Shdr) + sizeof(Elf_Ehdr)));
+    ehdr.e_phoff = 0;
+    ehdr.e_shoff = sizeof(Elf_Ehdr);
+    ehdr.e_phentsize = 0;
+    ehdr.e_phnum = 0;
+    ehdr.e_shstrndx = SHN_UNDEF;
+    memcpy(p + sizeof(int), &ehdr, sizeof(Elf_Ehdr));
+    *(int *)p = maxva - *symtab_addr;
+
+    /* Copy total length, crafted ELF header and section header table */
+    s = sizeof(int) + sizeof(Elf_Ehdr) + ehdr.e_shnum * sizeof(Elf_Shdr);
+    for ( i = 0; i < s; i += c, symva += c ) 
+    {
+        c = PAGE_SIZE - (symva & (PAGE_SIZE - 1));
+        if ( c > s - i )
+            c = s - i;
+        vaddr = map_pfn_writeable(pm_handle, 
+                                  page_array[(symva - *virt_load_addr)
+                                            >> PAGE_SHIFT]);
+        if ( vaddr == NULL )
+        {
+            ERROR("Couldn't map guest memory");
+            goto out;
+        }
+        DPRINTF(("copy page %p to %p, count 0x%x\n", (void *)symva,
+                 vaddr + (symva & (PAGE_SIZE - 1)), c));
+        memcpy(vaddr + (symva & (PAGE_SIZE - 1)), p + i,
+               c);
+        unmap_pfn(pm_handle, vaddr);
+    }
+
+    *symtab_len = maxva - *symtab_addr;
+
+    ret = 0;
+
+ out:
+    if ( ret == 0 )
+    {
+        maxva = (maxva + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+        *ksize = (maxva - *virt_load_addr) >> PAGE_SHIFT;
+
+        DPRINTF(("virt_addr %p, kpages 0x%lx, symtab_addr %p, symtab_len %p\n",
+                 (void *)*virt_load_addr, *ksize, (void *)*symtab_addr,
+                 (void *)*symtab_len));
+    }
+
+    if ( phdr != NULL )
+        free(phdr);
+    if ( p != NULL )
+        free(p);
+    return ret;
+}
diff --git a/tools/libxc/xc_physdev.c b/tools/libxc/xc_physdev.c
new file mode 100644 (file)
index 0000000..ba5dd9c
--- /dev/null
@@ -0,0 +1,29 @@
+/******************************************************************************
+ * xc_physdev.c
+ * 
+ * API for manipulating physical-device access permissions.
+ * 
+ * Copyright (c) 2004, Rolf Neugebauer (Intel Research Cambridge)
+ * Copyright (c) 2004, K A Fraser (University of Cambridge)
+ */
+
+#include "xc_private.h"
+
+int xc_physdev_pci_access_modify(int xc_handle,
+                                 u32 domid,
+                                 int bus,
+                                 int dev,
+                                 int func,
+                                 int enable)
+{
+    dom0_op_t op;
+
+    op.cmd = DOM0_PCIDEV_ACCESS;
+    op.u.pcidev_access.domain = (domid_t)domid;
+    op.u.pcidev_access.bus    = bus;
+    op.u.pcidev_access.dev    = dev;
+    op.u.pcidev_access.func   = func;
+    op.u.pcidev_access.enable = enable;
+
+    return do_dom0_op(xc_handle, &op);
+}
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
new file mode 100644 (file)
index 0000000..344f482
--- /dev/null
@@ -0,0 +1,230 @@
+/******************************************************************************
+ * xc_private.c
+ * 
+ * Helper functions for the rest of the library.
+ */
+
+#include "xc_private.h"
+
+int init_pfn_mapper(domid_t domid)
+{
+    int fd = open("/dev/mem", O_RDWR);
+    if ( fd >= 0 )
+        (void)ioctl(fd, _IO('M', 1), (unsigned long)domid);
+    return fd;
+}
+
+int close_pfn_mapper(int pm_handle)
+{
+    return close(pm_handle);
+}
+
+void *map_pfn_writeable(int pm_handle, unsigned long pfn)
+{
+    void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
+                       MAP_SHARED, pm_handle, pfn << PAGE_SHIFT);
+    if ( vaddr == MAP_FAILED )
+        return NULL;
+    return vaddr;
+}
+
+void *map_pfn_readonly(int pm_handle, unsigned long pfn)
+{
+    void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ,
+                       MAP_SHARED, pm_handle, pfn << PAGE_SHIFT);
+    if ( vaddr == MAP_FAILED )
+        return NULL;
+    return vaddr;
+}
+
+void unmap_pfn(int pm_handle, void *vaddr)
+{
+    (void)munmap(vaddr, PAGE_SIZE);
+}
+
+/*******************/
+
+void * mfn_mapper_map_batch(int xc_handle, domid_t dom, int prot,
+                            unsigned long *arr, int num )
+{
+    privcmd_mmapbatch_t ioctlx; 
+    void *addr;
+    addr = mmap( NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0 );
+    if (addr)
+    {
+        ioctlx.num=num;
+        ioctlx.dom=dom;
+        ioctlx.addr=(unsigned long)addr;
+        ioctlx.arr=arr;
+        if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx ) < 0 )
+        {
+            perror("XXXXXXXX");
+            munmap(addr, num*PAGE_SIZE);
+            return 0;
+        }
+    }
+    return addr;
+
+}
+
+/*******************/
+
+void * mfn_mapper_map_single(int xc_handle, domid_t dom,
+                             int size, int prot,
+                             unsigned long mfn )
+{
+    privcmd_mmap_t ioctlx; 
+    privcmd_mmap_entry_t entry; 
+    void *addr;
+    addr = mmap( NULL, size, prot, MAP_SHARED, xc_handle, 0 );
+    if (addr)
+    {
+        ioctlx.num=1;
+        ioctlx.dom=dom;
+        ioctlx.entry=&entry;
+        entry.va=(unsigned long) addr;
+        entry.mfn=mfn;
+        entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT;
+        if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) <0 )
+        {
+            munmap(addr, size);
+            return 0;
+        }
+    }
+    return addr;
+}
+
+/*******************/
+
+/* NB: arr must be mlock'ed */
+int get_pfn_type_batch(int xc_handle, 
+                       u32 dom, int num, unsigned long *arr)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_GETPAGEFRAMEINFO2;
+    op.u.getpageframeinfo2.domain = (domid_t)dom;
+    op.u.getpageframeinfo2.num    = num;
+    op.u.getpageframeinfo2.array  = arr;
+    return do_dom0_op(xc_handle, &op);
+}
+
+#define GETPFN_ERR (~0U)
+unsigned int get_pfn_type(int xc_handle, 
+                          unsigned long mfn, 
+                          u32 dom)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_GETPAGEFRAMEINFO;
+    op.u.getpageframeinfo.pfn    = mfn;
+    op.u.getpageframeinfo.domain = (domid_t)dom;
+    if ( do_dom0_op(xc_handle, &op) < 0 )
+    {
+        PERROR("Unexpected failure when getting page frame info!");
+        return GETPFN_ERR;
+    }
+    return op.u.getpageframeinfo.type;
+}
+
+
+
+/*******************/
+
+#define FIRST_MMU_UPDATE 1
+
+static int flush_mmu_updates(int xc_handle, mmu_t *mmu)
+{
+    int err = 0;
+    privcmd_hypercall_t hypercall;
+
+    if ( mmu->idx == FIRST_MMU_UPDATE )
+        return 0;
+
+    /* The first two requests set the correct subject domain (PTS and GPS). */
+    mmu->updates[0].val  = (unsigned long)(mmu->subject<<16) & ~0xFFFFUL;
+    mmu->updates[0].ptr  = (unsigned long)(mmu->subject<< 0) & ~0xFFFFUL;
+    mmu->updates[0].ptr |= MMU_EXTENDED_COMMAND;
+    mmu->updates[0].val |= MMUEXT_SET_SUBJECTDOM | SET_PAGETABLE_SUBJECTDOM;
+
+    hypercall.op     = __HYPERVISOR_mmu_update;
+    hypercall.arg[0] = (unsigned long)mmu->updates;
+    hypercall.arg[1] = (unsigned long)mmu->idx;
+    hypercall.arg[2] = 0;
+
+    if ( mlock(mmu->updates, sizeof(mmu->updates)) != 0 )
+    {
+        PERROR("Could not lock pagetable update array");
+        err = 1;
+        goto out;
+    }
+
+    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
+    {
+        ERROR("Failure when submitting mmu updates");
+        err = 1;
+    }
+
+    mmu->idx = FIRST_MMU_UPDATE;
+    
+    (void)munlock(mmu->updates, sizeof(mmu->updates));
+
+ out:
+    return err;
+}
+
+mmu_t *init_mmu_updates(int xc_handle, domid_t dom)
+{
+    mmu_t *mmu = malloc(sizeof(mmu_t));
+    if ( mmu == NULL )
+        return mmu;
+    mmu->idx     = FIRST_MMU_UPDATE;
+    mmu->subject = dom;
+    return mmu;
+}
+
+int add_mmu_update(int xc_handle, mmu_t *mmu, 
+                   unsigned long ptr, unsigned long val)
+{
+    mmu->updates[mmu->idx].ptr = ptr;
+    mmu->updates[mmu->idx].val = val;
+
+    if ( ++mmu->idx == MAX_MMU_UPDATES )
+        return flush_mmu_updates(xc_handle, mmu);
+
+    return 0;
+}
+
+int finish_mmu_updates(int xc_handle, mmu_t *mmu)
+{
+    return flush_mmu_updates(xc_handle, mmu);
+}
+
+
+long long  xc_domain_get_cpu_usage( int xc_handle, domid_t domid )
+{
+    dom0_op_t op;
+
+    op.cmd = DOM0_GETDOMAININFO;
+    op.u.getdomaininfo.domain = (domid_t)domid;
+    op.u.getdomaininfo.ctxt = NULL;
+    if ( (do_dom0_op(xc_handle, &op) < 0) || 
+         ((u32)op.u.getdomaininfo.domain != domid) )
+    {
+        PERROR("Could not get info on domain");
+        return -1;
+    }
+    return op.u.getdomaininfo.cpu_time;
+}
+
+
+/* This is shared between save and restore, and may generally be useful. */
+unsigned long csum_page (void * page)
+{
+    int i;
+    unsigned long *p = page;
+    unsigned long long sum=0;
+
+    for ( i = 0; i < (PAGE_SIZE/sizeof(unsigned long)); i++ )
+        sum += p[i];
+
+    return sum ^ (sum>>32);
+}
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
new file mode 100644 (file)
index 0000000..7421851
--- /dev/null
@@ -0,0 +1,213 @@
+
+#ifndef __XC_PRIVATE_H__
+#define __XC_PRIVATE_H__
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <string.h>
+
+#include "xc.h"
+
+/* from xen/include/hypervisor-ifs */
+#include <hypervisor-if.h>
+#include <dom0_ops.h>
+#include <event_channel.h>
+#include <sched_ctl.h>
+
+#include <asm-xen/proc_cmd.h>
+
+/* from xend/lib */
+#include <domain_controller.h>
+
+#define _PAGE_PRESENT   0x001
+#define _PAGE_RW        0x002
+#define _PAGE_USER      0x004
+#define _PAGE_PWT       0x008
+#define _PAGE_PCD       0x010
+#define _PAGE_ACCESSED  0x020
+#define _PAGE_DIRTY     0x040
+#define _PAGE_PAT       0x080
+#define _PAGE_PSE       0x080
+#define _PAGE_GLOBAL    0x100
+
+
+#define L1_PAGETABLE_SHIFT       12
+#define L2_PAGETABLE_SHIFT       22
+#define ENTRIES_PER_L1_PAGETABLE 1024
+#define ENTRIES_PER_L2_PAGETABLE 1024
+#define PAGE_SHIFT              L1_PAGETABLE_SHIFT
+#define PAGE_SIZE               (1UL << PAGE_SHIFT)
+#define PAGE_MASK               (~(PAGE_SIZE-1))
+
+typedef unsigned long l1_pgentry_t;
+typedef unsigned long l2_pgentry_t;
+
+#define l1_table_offset(_a) \
+          (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
+#define l2_table_offset(_a) \
+          ((_a) >> L2_PAGETABLE_SHIFT)
+
+#define ERROR(_m, _a...)  \
+    fprintf(stderr, "ERROR: " _m "\n" , ## _a )
+
+#define PERROR(_m, _a...) \
+    fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
+            errno, strerror(errno))
+
+static inline int do_privcmd(int xc_handle,
+                             unsigned int cmd, 
+                             unsigned long data)
+{
+    return ioctl(xc_handle, cmd, data);
+}
+
+static inline int do_xen_hypercall(int xc_handle,
+                                   privcmd_hypercall_t *hypercall)
+{
+    return do_privcmd(xc_handle,
+                      IOCTL_PRIVCMD_HYPERCALL, 
+                      (unsigned long)hypercall);
+}
+
+static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
+{
+    int ret = -1;
+    privcmd_hypercall_t hypercall;
+
+    op->interface_version = DOM0_INTERFACE_VERSION;
+
+    hypercall.op     = __HYPERVISOR_dom0_op;
+    hypercall.arg[0] = (unsigned long)op;
+
+    if ( mlock(op, sizeof(*op)) != 0 )
+    {
+        PERROR("Could not lock memory for Xen hypercall");
+        goto out1;
+    }
+
+    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
+    {
+        if ( errno == EACCES )
+            fprintf(stderr, "Dom0 operation failed -- need to"
+                    " rebuild the user-space tool set?\n");
+        goto out2;
+    }
+
+ out2: (void)munlock(op, sizeof(*op));
+ out1: return ret;
+}
+
+static inline int do_multicall_op(int xc_handle, 
+                                 void *call_list, int nr_calls) 
+{
+    int ret = -1;
+    privcmd_hypercall_t hypercall;
+
+    hypercall.op     = __HYPERVISOR_multicall;
+    hypercall.arg[0] = (unsigned long)call_list;
+    hypercall.arg[1] = (unsigned long)nr_calls;
+
+    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
+    {
+        if ( errno == EACCES )
+            fprintf(stderr, "Dom0 operation failed -- need to"
+                    " rebuild the user-space tool set?\n");
+        goto out1;
+    }
+
+ out1: return ret;
+}
+
+/*
+ * PFN mapping.
+ */
+int init_pfn_mapper(domid_t domid);
+int close_pfn_mapper(int pm_handle);
+void *map_pfn_writeable(int pm_handle, unsigned long pfn);
+void *map_pfn_readonly(int pm_handle, unsigned long pfn);
+void unmap_pfn(int pm_handle, void *vaddr);
+int get_pfn_type_batch(int xc_handle, u32 dom, int num, unsigned long *arr);
+unsigned long csum_page (void * page);
+
+/*
+ * MMU updates.
+ */
+#define MAX_MMU_UPDATES 1024
+typedef struct {
+    mmu_update_t updates[MAX_MMU_UPDATES];
+    int          idx;
+    domid_t      subject;
+} mmu_t;
+mmu_t *init_mmu_updates(int xc_handle, domid_t dom);
+int add_mmu_update(int xc_handle, mmu_t *mmu, 
+                   unsigned long ptr, unsigned long val);
+int finish_mmu_updates(int xc_handle, mmu_t *mmu);
+
+
+/*
+ * ioctl-based mfn mapping interface
+ */
+
+/*
+typedef struct privcmd_mmap_entry {
+    unsigned long va;
+    unsigned long mfn;
+    unsigned long npages;
+} privcmd_mmap_entry_t; 
+
+typedef struct privcmd_mmap {
+    int num;
+    domid_t dom;
+    privcmd_mmap_entry_t *entry;
+} privcmd_mmap_t; 
+*/
+
+#define mfn_mapper_queue_size 128
+
+typedef struct mfn_mapper {
+    int xc_handle;
+    int size;
+    int prot;
+    int error;
+    int max_queue_size;
+    void * addr;
+    privcmd_mmap_t ioctl; 
+    
+} mfn_mapper_t;
+
+void * mfn_mapper_map_single(int xc_handle, domid_t dom, int size, int prot, 
+                            unsigned long mfn );
+
+void * mfn_mapper_map_batch(int xc_handle, domid_t dom, int prot,
+                           unsigned long *arr, int num );
+
+mfn_mapper_t * mfn_mapper_init(int xc_handle, domid_t dom, int size, int prot);
+
+void * mfn_mapper_base(mfn_mapper_t *t);
+
+void mfn_mapper_close(mfn_mapper_t *t);
+
+int mfn_mapper_flush_queue(mfn_mapper_t *t);
+
+void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, 
+                             unsigned long mfn, int size );
+
+long long  xc_domain_get_cpu_usage( int xc_handle, domid_t domid );
+
+#include "xc_io.h"
+
+int xc_domain_getfullinfo(int xc_handle,
+                          u32 domid,
+                          dom0_op_t *op,
+                          full_execution_context_t *ctxt );
+#endif /* __XC_PRIVATE_H__ */
diff --git a/tools/libxc/xc_rrobin.c b/tools/libxc/xc_rrobin.c
new file mode 100644 (file)
index 0000000..ad37962
--- /dev/null
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * xc_rrobin.c
+ * 
+ * API for manipulating parameters of the Round Robin scheduler
+ * 
+ * by Mark Williamson, Copyright (c) 2004 Intel Research Cambridge.
+ */
+
+#include "xc_private.h"
+
+int xc_rrobin_global_set(int xc_handle, u64 slice)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_SCHEDCTL;
+    op.u.schedctl.sched_id = SCHED_RROBIN;
+    op.u.schedctl.direction = SCHED_INFO_PUT;
+
+    op.u.schedctl.u.rrobin.slice = slice;
+    return do_dom0_op(xc_handle, &op);
+}
+
+
+int xc_rrobin_global_get(int xc_handle, u64 *slice)
+{
+    dom0_op_t op;
+    int ret;
+
+    op.cmd = DOM0_SCHEDCTL;
+    op.u.schedctl.sched_id = SCHED_RROBIN;
+    op.u.schedctl.direction = SCHED_INFO_GET;
+
+    ret = do_dom0_op(xc_handle, &op);
+
+    *slice = op.u.schedctl.u.rrobin.slice;
+
+    return ret;
+}
diff --git a/tools/libxutil/Makefile b/tools/libxutil/Makefile
new file mode 100644 (file)
index 0000000..0e92fa7
--- /dev/null
@@ -0,0 +1,80 @@
+XEN_ROOT = ../..
+include $(XEN_ROOT)/tools/Make.defs
+
+CC = gcc
+
+LIB_SRCS :=
+LIB_SRCS += allocate.c
+#LIB_SRCS += enum.c
+LIB_SRCS += file_stream.c
+LIB_SRCS += gzip_stream.c
+#LIB_SRCS += hash_table.c
+LIB_SRCS += iostream.c
+#LIB_SRCS += kernel_stream.c
+#LIB_SRCS += lexis.c
+#LIB_SRCS += lzi_stream.c
+#LIB_SRCS += lzo_stream.c
+#LIB_SRCS += marshal.c
+#LIB_SRCS += socket_stream.c
+#LIB_SRCS += string_stream.c
+#LIB_SRCS += sxpr.c
+#LIB_SRCS += sxpr_parser.c
+LIB_SRCS += sys_net.c
+LIB_SRCS += sys_string.c
+#LIB_SRCS += xdr.c
+
+LIB_OBJS := $(LIB_SRCS:.c=.o)
+
+CFLAGS   += -Wall
+CFLAGS   += -Werror
+CFLAGS   += -g
+CFLAGS   += -O3
+CFLAGS   += -fno-strict-aliasing
+#CFLAGS   += $(INCLUDES)
+# Get gcc to generate the dependencies for us.
+CFLAGS   += -Wp,-MD,.$(@F).d
+DEPS     = .*.d
+
+MAJOR    = 1.3
+MINOR    = 0
+LIB_NAME = libxutil
+LIB_BASE = $(LIB_NAME).so
+LIB_MAJOR= $(LIB_BASE).$(MAJOR)
+LIB_MINOR= $(LIB_MAJOR).$(MINOR)
+LIB      = $(LIB_BASE) $(LIB_MAJOR) $(LIB_MINOR) $(LIB_NAME).a
+
+all: check-for-zlib $(LIB)
+
+$(LIB_BASE):
+       ln -sf $(LIB_MAJOR) $@
+
+$(LIB_MAJOR):
+       ln -sf $(LIB_MINOR) $@
+
+$(LIB_MINOR): $(LIB_OBJS)
+       $(CC) -Wl,-soname -Wl,$(LIB_MAJOR) -shared -o $@ $^
+
+$(LIB_NAME).a: $(LIB_OBJS)
+       $(AR) rc $@ $^
+
+check-for-zlib:
+       @if [ ! -e /usr/include/zlib.h ]; then \
+       echo "***********************************************************"; \
+       echo "ERROR: install zlib header files (http://www.gzip.org/zlib)"; \
+       echo "***********************************************************"; \
+       false; \
+       fi
+
+install: all
+       mkdir -p $(prefix)/usr/lib
+       mkdir -p $(prefix)/usr/include
+       install -m0755 $(LIB) $(prefix)/usr/lib
+
+#install -m0644 xc.h $(prefix)/usr/include
+
+clean:
+       $(RM) *.a *.so *.o *.rpm $(LIB)
+       $(RM) *~
+       $(RM) $(DEPS)
+
+-include $(DEPS)
diff --git a/tools/libxutil/allocate.c b/tools/libxutil/allocate.c
new file mode 100644 (file)
index 0000000..600ebab
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "allocate.h"
+
+/** @file
+ * Support for allocating memory.
+ * Usable from user code or kernel code (with __KERNEL__ defined).
+ * In user code will use GC if USE_GC is defined.
+ */
+
+#ifdef __KERNEL__
+/*----------------------------------------------------------------------------*/
+#  include <linux/config.h>
+#  include <linux/slab.h>
+#  include <linux/string.h>
+#  include <linux/types.h>
+
+#  define DEFAULT_TYPE    0
+#  define MALLOC(n, type) kmalloc(n, type)
+#  define FREE(ptr)       kfree(ptr)
+
+/*----------------------------------------------------------------------------*/
+#else /* ! __KERNEL__ */
+
+#  include <stdlib.h>
+#  include <string.h>
+
+#  define DEFAULT_TYPE    0
+
+#ifdef USE_GC
+#  include "gc.h"
+#  define MALLOC(n, typ)  GC_malloc(n)
+#  define FREE(ptr)       (ptr=NULL)
+//typedef void *GC_PTR;
+//GC_PTR (*GC_oom_fn)(size_t n);
+#else
+#  define MALLOC(n, type) malloc(n)
+#  define FREE(ptr)       free(ptr)
+#endif
+
+/*----------------------------------------------------------------------------*/
+#endif
+
+/** Function to call when memory cannot be allocated. */
+AllocateFailedFn *allocate_failed_fn = NULL;
+
+/** Allocate memory and zero it.
+ * The type is only relevant when calling from kernel code,
+ * from user code it is ignored.
+ * In kernel code the values accepted by kmalloc can be used:
+ * GFP_USER, GFP_ATOMIC, GFP_KERNEL.
+ *
+ * @param size number of bytes to allocate
+ * @param type memory type to allocate (kernel only)
+ * @return pointer to the allocated memory or zero
+ * if malloc failed
+ */
+void *allocate_type(int size, int type){
+    void *p = MALLOC(size, type);
+    if(p){
+        memzero(p, size);
+    } else if(allocate_failed_fn){
+        allocate_failed_fn(size, type);
+    }
+    return p;
+}
+
+/** Allocate memory and zero it.
+ *
+ * @param size number of bytes to allocate
+ * @return pointer to the allocated memory or zero
+ * if malloc failed
+ */
+void *allocate(int size){
+    return allocate_type(size, DEFAULT_TYPE);
+}
+
+/** Free memory allocated by allocate().
+ * No-op if 'p' is null.
+ *
+ * @param p memory to free
+ */
+void deallocate(void *p){
+    if(p){
+        FREE(p);
+    }
+}
+
+/** Set bytes to zero.
+ * No-op if 'p' is null.
+ *
+ * @param p memory to zero
+ * @param size number of bytes to zero
+ */
+void memzero(void *p, int size){
+    if(p){
+        memset(p, 0, (size_t)size);
+    }
+}
+
diff --git a/tools/libxutil/allocate.h b/tools/libxutil/allocate.h
new file mode 100644 (file)
index 0000000..08bc67b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _XEN_LIB_ALLOCATE_H_
+#define _XEN_LIB_ALLOCATE_H_
+
+/** Allocate memory for a given type, and cast. */
+#define ALLOCATE(ctype) (ctype *)allocate(sizeof(ctype))
+
+/** Allocate memory for a given type, and cast. */
+#define ALLOCATE_TYPE(ctype, type) (ctype *)allocate(sizeof(ctype))
+
+extern void *allocate_type(int size, int type);
+extern void *allocate(int size);
+extern void deallocate(void *);
+extern void memzero(void *p, int size);
+
+typedef void AllocateFailedFn(int size, int type);
+extern AllocateFailedFn *allocate_failed_fn;
+
+#endif /* _XEN_LIB_ALLOCATE_H_ */
+
+
+
+
+
+
+
+
+
diff --git a/tools/libxutil/debug.h b/tools/libxutil/debug.h
new file mode 100644 (file)
index 0000000..4f5228f
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _XEN_LIB_DEBUG_H_
+#define _XEN_LIB_DEBUG_H_
+
+#ifndef MODULE_NAME
+#define MODULE_NAME ""
+#endif
+
+#ifdef __KERNEL__
+#include <linux/config.h>
+#include <linux/kernel.h>
+
+#ifdef DEBUG
+
+#define dprintf(fmt, args...) printk(KERN_DEBUG   "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
+#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
+#define iprintf(fmt, args...) printk(KERN_INFO    "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
+#define eprintf(fmt, args...) printk(KERN_ERR     "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
+
+#else
+
+#define dprintf(fmt, args...) do {} while(0)
+#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME fmt, ##args)
+#define iprintf(fmt, args...) printk(KERN_INFO    "[INF] " MODULE_NAME fmt, ##args)
+#define eprintf(fmt, args...) printk(KERN_ERR     "[ERR] " MODULE_NAME fmt, ##args)
+
+#endif
+
+#else
+
+#include <stdio.h>
+
+#ifdef DEBUG
+
+#define dprintf(fmt, args...) fprintf(stdout, "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
+#define wprintf(fmt, args...) fprintf(stderr, "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
+#define iprintf(fmt, args...) fprintf(stderr, "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
+#define eprintf(fmt, args...) fprintf(stderr, "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
+
+#else
+
+#define dprintf(fmt, args...) do {} while(0)
+#define wprintf(fmt, args...) fprintf(stderr, "[WRN] " MODULE_NAME fmt, ##args)
+#define iprintf(fmt, args...) fprintf(stderr, "[INF] " MODULE_NAME fmt, ##args)
+#define eprintf(fmt, args...) fprintf(stderr, "[ERR] " MODULE_NAME fmt, ##args)
+
+#endif
+
+#endif
+
+/** Print format for an IP address.
+ * See NIPQUAD(), HIPQUAD()
+ */
+#define IPFMT "%u.%u.%u.%u"
+
+#endif /* ! _XEN_LIB_DEBUG_H_ */
diff --git a/tools/libxutil/enum.c b/tools/libxutil/enum.c
new file mode 100644 (file)
index 0000000..95f6e31
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or  (at your option) any later version. This library is 
+ * distributed in the  hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifdef __KERNEL__
+#include <linux/errno.h>
+#else
+#include <errno.h>
+#endif
+
+#include "sys_string.h"
+#include "enum.h"
+
+/** Map an enum name to its value using a table.
+ *
+ * @param name enum name
+ * @param defs enum definitions
+ * @return enum value or -1 if not known
+ */
+int enum_name_to_val(char *name, EnumDef *defs){
+    int val = -1;
+    for(; defs->name; defs++){
+       if(!strcmp(defs->name, name)){
+           val = defs->val;
+           break;
+       }
+    }
+    return val;
+}
+
+/** Map an enum value to its name using a table.
+ *
+ * @param val enum value
+ * @param defs enum definitions
+ * @param defs_n number of definitions
+ * @return enum name or NULL if not known
+ */
+char *enum_val_to_name(int val, EnumDef *defs){
+    char *name = NULL;
+    for(; defs->name; defs++){
+       if(val == defs->val){
+           name = defs->name;
+           break;
+       }
+    }
+    return name;
+}
+
diff --git a/tools/libxutil/enum.h b/tools/libxutil/enum.h
new file mode 100644 (file)
index 0000000..db6e7b0
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or  (at your option) any later version. This library is 
+ * distributed in the  hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef _XEN_LIB_ENUM_H_
+#define _XEN_LIB_ENUM_H_
+
+/** Mapping of an enum value to a name. */
+typedef struct EnumDef {
+    int val;
+    char *name;
+} EnumDef;
+
+extern int enum_name_to_val(char *name, EnumDef *defs);
+extern char *enum_val_to_name(int val, EnumDef *defs);
+
+#endif /* _XEN_LIB_ENUM_H_ */
diff --git a/tools/libxutil/file_stream.c b/tools/libxutil/file_stream.c
new file mode 100644 (file)
index 0000000..40391f7
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/** @file
+ * An IOStream implementation using FILE*.
+ */
+#ifndef __KERNEL__
+#include <stdio.h>
+#include <stdlib.h>
+#include "allocate.h"
+#include "file_stream.h"
+
+static int file_read(IOStream *s, void *buf, size_t n);
+static int file_write(IOStream *s, const void *buf, size_t n);
+static int file_error(IOStream *s);
+static int file_close(IOStream *s);
+static void file_free(IOStream *s);
+static int file_flush(IOStream *s);
+
+/** Methods used by a FILE* IOStream. */
+static const IOMethods file_methods = {
+    read:  file_read,
+    write: file_write,
+    error: file_error,
+    close: file_close,
+    free:  file_free,
+    flush: file_flush,
+};
+
+/** IOStream for stdin. */
+static IOStream _iostdin = {
+    methods: &file_methods,
+    data: (void*)1,
+};
+
+/** IOStream for stdout. */
+static IOStream _iostdout = {
+    methods: &file_methods,
+    data: (void*)2,
+};
+
+/** IOStream for stderr. */
+static IOStream _iostderr = {
+    methods: &file_methods,
+    data: (void*)3,
+};
+
+/** IOStream for stdin. */
+IOStream *iostdin = &_iostdin;
+
+/** IOStream for stdout. */
+IOStream *iostdout = &_iostdout;
+
+/** IOStream for stderr. */
+IOStream *iostderr = &_iostderr;
+
+/** Get the underlying FILE*.
+ * 
+ * @param s file stream
+ * @return the stream s wraps
+ */
+static inline FILE *get_file(IOStream *s){
+    switch((long)s->data){
+    case 1: s->data = stdin; break;
+    case 2: s->data = stdout; break;
+    case 3: s->data = stderr; break;
+    }
+    return (FILE*)s->data;
+}
+
+/** Control buffering on the underlying stream, like setvbuf().
+ *
+ * @param io file stream
+ * @param buf buffer
+ * @param mode buffering mode (see man setvbuf())
+ * @param size buffer size
+ * @return 0 on success, non-zero otherwise
+ */
+int file_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size){
+    return setvbuf(get_file(io), buf, mode, size);
+}
+
+/** Write to the underlying stream using fwrite();
+ *
+ * @param stream input
+ * @param buf where to put input
+ * @param n number of bytes to write
+ * @return number of bytes written
+ */
+static int file_write(IOStream *s, const void *buf, size_t n){
+    return fwrite(buf, 1, n, get_file(s));
+}
+
+/** Read from the underlying stream using fread();
+ *
+ * @param stream input
+ * @param buf where to put input
+ * @param n number of bytes to read
+ * @return number of bytes read
+ */
+static int file_read(IOStream *s, void *buf, size_t n){
+    return fread(buf, 1, n, get_file(s));
+}
+
+/** Fush the underlying stream using fflush().
+ *
+ * @param s file stream
+ * @return 0 on success, error code otherwise
+ */
+static int file_flush(IOStream *s){
+    return fflush(get_file(s));
+}
+
+/** Check if a stream has an error.
+ *
+ * @param s file stream
+ * @return 1 if has an error, 0 otherwise
+ */
+static int file_error(IOStream *s){
+    return ferror(get_file(s));
+}
+
+/** Close a file stream.
+ *
+ * @param s file stream to close
+ * @return result of the close
+ */
+static int file_close(IOStream *s){
+    return fclose(get_file(s));
+}
+
+/** Free a file stream.
+ *
+ * @param s file stream
+ */
+static void file_free(IOStream *s){
+    // Do nothing - fclose does it all?
+}
+
+/** Create an IOStream for a stream.
+ *
+ * @param f stream to wrap
+ * @return new IOStream using f for i/o
+ */
+IOStream *file_stream_new(FILE *f){
+    IOStream *io = ALLOCATE(IOStream);
+    if(io){
+       io->methods = &file_methods;
+       io->data = (void*)f;
+    }
+    return io;
+}
+
+/** IOStream version of fopen().
+ *
+ * @param file name of the file to open
+ * @param flags giving the mode to open in (as for fopen())
+ * @return new stream for the open file, or 0 if failed
+ */
+IOStream *file_stream_fopen(const char *file, const char *flags){
+    IOStream *io = 0;
+    FILE *fin = fopen(file, flags);
+    if(fin){
+       io = file_stream_new(fin);
+       if(!io){
+           fclose(fin);
+           //free(fin); // fclose frees ?
+       }
+    }
+    return io;
+}
+
+/** IOStream version of fdopen().
+ *
+ * @param fd file descriptor
+ * @param flags giving the mode to open in (as for fdopen())
+ * @return new stream for the open file, or 0 if failed
+ */
+IOStream *file_stream_fdopen(int fd, const char *flags){
+    IOStream *io = 0;
+    FILE *fin = fdopen(fd, flags);
+    if(fin){
+       io = file_stream_new(fin);
+    }
+    return io;
+}
+#endif
diff --git a/tools/libxutil/file_stream.h b/tools/libxutil/file_stream.h
new file mode 100644 (file)
index 0000000..36a0f92
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _XEN_LIB_FILE_STREAM_H_
+#define _XEN_LIB_FILE_STREAM_H_
+
+#ifndef __KERNEL__
+#include "iostream.h"
+#include <stdio.h>
+
+extern IOStream *file_stream_new(FILE *f);
+extern IOStream *file_stream_fopen(const char *file, const char *flags);
+extern IOStream *file_stream_fdopen(int fd, const char *flags);
+extern IOStream get_stream_stdout(void);
+extern IOStream get_stream_stderr(void);
+extern IOStream get_stream_stdin(void);
+
+extern int file_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size);
+#endif
+#endif /* !_XEN_LIB_FILE_STREAM_H_ */
diff --git a/tools/libxutil/gzip_stream.c b/tools/libxutil/gzip_stream.c
new file mode 100644 (file)
index 0000000..af46023
--- /dev/null
@@ -0,0 +1,171 @@
+/* $Id: gzip_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */
+/*
+ * Copyright (C) 2003 Hewlett-Packard Company.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/** @file
+ * An IOStream implementation using zlib gzFile to provide
+ * compression and decompression.
+ */
+#ifndef __KERNEL__
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "zlib.h"
+
+#include "allocate.h"
+#include "gzip_stream.h"
+
+static int gzip_read(IOStream *s, void *buf, size_t n);
+static int gzip_write(IOStream *s, const void *buf, size_t n);
+static int gzip_error(IOStream *s);
+static int gzip_close(IOStream *s);
+static void gzip_free(IOStream *s);
+static int gzip_flush(IOStream *s);
+
+/** Methods used by a gzFile* IOStream. */
+static const IOMethods gzip_methods = {
+    read: gzip_read,
+    write: gzip_write,
+    error: gzip_error,
+    close: gzip_close,
+    free:  gzip_free,
+    flush: gzip_flush,
+};
+
+/** Get the underlying gzFile*.
+ * 
+ * @param s gzip stream
+ * @return the stream s wraps
+ */
+static inline gzFile get_gzfile(IOStream *s){
+    return (gzFile)s->data;
+}
+
+/** Write to the underlying stream.
+ *
+ * @param stream destination
+ * @param buf data
+ * @param n number of bytes to write
+ * @return number of bytes written
+ */
+static int gzip_write(IOStream *s, const void *buf, size_t n){
+    return gzwrite(get_gzfile(s), (void*)buf, n);
+}
+
+/** Read from the underlying stream.
+ *
+ * @param stream input
+ * @param buf where to put input
+ * @param n number of bytes to read
+ * @return number of bytes read
+ */
+static int gzip_read(IOStream *s, void *buf, size_t n){
+    return gzread(get_gzfile(s), buf, n);
+}
+
+/** Flush the underlying stream.
+ *
+ * @param s gzip stream
+ * @return 0 on success, error code otherwise
+ */
+static int gzip_flush(IOStream *s){
+    //return gzflush(get_gzfile(s), Z_NO_FLUSH);
+    return gzflush(get_gzfile(s), Z_SYNC_FLUSH);
+    //return gzflush(get_gzfile(s), Z_FULL_FLUSH);
+}
+
+/** Check if a stream has an error.
+ *
+ * @param s gzip stream
+ * @return 1 if has an error, 0 otherwise
+ */
+static int gzip_error(IOStream *s){
+    int err;
+    gzFile *gz = get_gzfile(s);
+    gzerror(gz, &err);
+    return (err == Z_ERRNO ? 1 /* ferror(gzfile(gz)) */ : err);
+}
+
+/** Close a gzip stream.
+ *
+ * @param s gzip stream to close
+ * @return result of the close
+ */
+static int gzip_close(IOStream *s){
+    return gzclose(get_gzfile(s));
+}
+
+/** Free a gzip stream.
+ *
+ * @param s gzip stream
+ */
+static void gzip_free(IOStream *s){
+    // Do nothing - fclose does it all?
+}
+
+/** Create an IOStream for a gzip stream.
+ *
+ * @param f stream to wrap
+ * @return new IOStream using f for i/o
+ */
+IOStream *gzip_stream_new(gzFile *f){
+    IOStream *io = ALLOCATE(IOStream);
+    if(io){
+       io->methods = &gzip_methods;
+       io->data = (void*)f;
+    }
+    return io;
+}
+
+/** IOStream version of fopen().
+ *
+ * @param file name of the file to open
+ * @param flags giving the mode to open in (as for fopen())
+ * @return new stream for the open file, or NULL if failed
+ */
+IOStream *gzip_stream_fopen(const char *file, const char *flags){
+    IOStream *io = NULL;
+    gzFile *fgz;
+    fgz = gzopen(file, flags);
+    if(fgz){
+       io = gzip_stream_new(fgz);
+       if(!io){
+           gzclose(fgz);
+           //free(fgz); // gzclose frees ?
+       }
+    }
+    return io;
+}
+
+/** IOStream version of fdopen().
+ *
+ * @param fd file descriptor
+ * @param flags giving the mode to open in (as for fdopen())
+ * @return new stream for the open file, or NULL if failed
+ */
+IOStream *gzip_stream_fdopen(int fd, const char *flags){
+    IOStream *io = NULL;
+    gzFile *fgz;
+    fgz = gzdopen(fd, flags);
+    if(fgz){
+       io = gzip_stream_new(fgz);
+    }
+    return io;
+}
+#endif
diff --git a/tools/libxutil/gzip_stream.h b/tools/libxutil/gzip_stream.h
new file mode 100644 (file)
index 0000000..cf76d25
--- /dev/null
@@ -0,0 +1,31 @@
+#/* $Id: gzip_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */
+/*
+ * Copyright (C) 2003 Hewlett-Packard Company.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _SP_GZIP_STREAM_H_
+#define _SP_GZIP_STREAM_H_
+
+#ifndef __KERNEL__
+#include "iostream.h"
+#include "zlib.h"
+
+extern IOStream *gzip_stream_new(gzFile *f);
+extern IOStream *gzip_stream_fopen(const char *file, const char *flags);
+extern IOStream *gzip_stream_fdopen(int fd, const char *flags);
+#endif
+#endif /* !_SP_FILE_STREAM_H_ */
diff --git a/tools/libxutil/hash_table.c b/tools/libxutil/hash_table.c
new file mode 100644 (file)
index 0000000..13da946
--- /dev/null
@@ -0,0 +1,640 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef __KERNEL__
+#  include <linux/config.h>
+#  include <linux/module.h>
+#  include <linux/kernel.h>
+#  include <linux/errno.h>
+#else
+#  include <errno.h>
+#  include <stddef.h>
+#endif
+
+//#include <limits.h>
+
+#include "allocate.h"
+#include "hash_table.h"
+
+/** @file
+ * Base support for hashtables.
+ *
+ * Hash codes are reduced modulo the number of buckets to index tables,
+ * so there is no need for hash functions to limit the range of hashcodes.
+ * In fact it is assumed that hashcodes do not change when the number of
+ * buckets in the table changes.
+ */
+
+/*==========================================================================*/
+/** Number of bits in half a word. */
+//#if __WORDSIZE == 64
+//#define HALF_WORD_BITS 32
+//#else
+#define HALF_WORD_BITS 16
+//#endif
+
+/** Mask for lo half of a word. On 32-bit this is 
+ * (1<<16) - 1 = 65535 = 0xffff
+ * It's 4294967295 = 0xffffffff on 64-bit.
+ */
+#define LO_HALF_MASK ((1 << HALF_WORD_BITS) - 1)
+
+/** Get the lo half of a word. */
+#define LO_HALF(x) ((x) & LO_HALF_MASK)
+
+/** Get the hi half of a word. */
+#define HI_HALF(x) ((x) >> HALF_WORD_BITS)
+
+/** Do a full hash on both inputs, using DES-style non-linear scrambling.
+ * Both inputs are replaced with the results of the hash.
+ *
+ * @param pleft input/output word
+ * @param pright input/output word
+ */
+void pseudo_des(unsigned long *pleft, unsigned long *pright){
+    // Bit-rich mixing constant.
+    static const unsigned long a_mixer[] = {
+        0xbaa96887L, 0x1e17d32cL, 0x03bcdc3cL, 0x0f33d1b2L, };
+
+    // Bit-rich mixing constant.
+    static const unsigned long b_mixer[] = {
+        0x4b0f3b58L, 0xe874f0c3L, 0x6955c5a6L, 0x55a7ca46L, };
+
+    // Number of iterations - must be 2 or 4.
+    static const int ncycle = 4;
+    //static const int ncycle = 2;
+
+    unsigned long left = *pleft, right = *pright;
+    unsigned long v, v_hi, v_lo;
+    int i;
+
+    for(i=0; i<ncycle; i++){
+        // Flip some bits in right to get v.
+        v = right;
+        v ^= a_mixer[i];
+        // Get lo and hi halves of v.
+        v_lo = LO_HALF(v);
+        v_hi = HI_HALF(v);
+        // Non-linear mix of the halves of v.
+        v = ((v_lo * v_lo) + ~(v_hi * v_hi));
+        // Swap the halves of v.
+        v = (HI_HALF(v) | (LO_HALF(v) << HALF_WORD_BITS));
+        // Flip some bits.
+        v ^= b_mixer[i];
+        // More non-linear mixing.
+        v += (v_lo * v_hi);
+        v ^= left;
+        left = right;
+        right = v;
+    }
+    *pleft = left;
+    *pright = right;
+}
+
+/** Hash a string.
+ *
+ * @param s input to hash
+ * @return hashcode
+ */
+Hashcode hash_string(char *s){
+    Hashcode h = 0;
+    if(s){
+        for( ; *s; s++){
+            h = hash_2ul(h, *s);
+        }
+    }
+    return h;
+}
+
+/** Get the bucket for a hashcode in a hash table.
+ *
+ * @param table to get bucket from
+ * @param hashcode to get bucket for
+ * @return bucket
+ */
+inline HTBucket * get_bucket(HashTable *table, Hashcode hashcode){
+    return table->buckets + (hashcode % table->buckets_n);
+}
+
+/** Initialize a hash table.
+ * Can be safely called more than once.
+ *
+ * @param table to initialize
+ */
+void HashTable_init(HashTable *table){
+    int i;
+
+    if(!table->init_done){
+        table->init_done = 1;
+        table->next_id = 0;
+        for(i=0; i<table->buckets_n; i++){
+            HTBucket *bucket = get_bucket(table, i);
+            bucket->head = 0;
+            bucket->count = 0;
+        }
+        table->entry_count = 0;
+    }
+}
+
+/** Allocate a new hashtable.
+ * If the number of buckets is not positive the default is used.
+ * The number of buckets should usually be prime.
+ *
+ * @param buckets_n number of buckets
+ * @return new hashtable or null
+ */
+HashTable *HashTable_new(int buckets_n){
+    HashTable *z = ALLOCATE(HashTable);
+    if(!z) goto exit;
+    if(buckets_n <= 0){
+        buckets_n = HT_BUCKETS_N;
+    }
+    z->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
+    if(!z->buckets){
+        deallocate(z);
+        z = 0;
+        goto exit;
+    }
+    z->buckets_n = buckets_n;
+    HashTable_init(z);
+  exit:
+    return z;
+}
+
+/** Free a hashtable.
+ * Any entries are removed and freed.
+ *
+ * @param h hashtable (ignored if null)
+ */
+void HashTable_free(HashTable *h){
+    if(h){
+        HashTable_clear(h);
+        deallocate(h->buckets);
+        deallocate(h);
+    }
+}
+
+/** Push an entry on the list in the bucket for a given hashcode.
+ *
+ * @param table to add entry to
+ * @param hashcode for the entry
+ * @param entry to add
+ */
+static inline void push_on_bucket(HashTable *table, Hashcode hashcode,
+                                 HTEntry *entry){
+    HTBucket *bucket;
+    HTEntry *old_head;
+
+    bucket = get_bucket(table, hashcode);
+    old_head = bucket->head;
+    bucket->count++;
+    bucket->head = entry;
+    entry->next = old_head;
+}
+
+/** Change the number of buckets in a hashtable.
+ * No-op if the number of buckets is not positive.
+ * Existing entries are reallocated to buckets based on their hashcodes.
+ * The table is unmodified if the number of buckets cannot be changed.
+ *
+ * @param table hashtable
+ * @param buckets_n new number of buckets
+ * @return 0 on success, error code otherwise
+ */
+int HashTable_set_buckets_n(HashTable *table, int buckets_n){
+    int err = 0;
+    HTBucket *old_buckets = table->buckets;
+    int old_buckets_n = table->buckets_n;
+    int i;
+
+    if(buckets_n <= 0){
+        err = -EINVAL;
+        goto exit;
+    }
+    table->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
+    if(!table->buckets){
+        err = -ENOMEM;
+        table->buckets = old_buckets;
+        goto exit;
+    }
+    table->buckets_n = buckets_n;
+    for(i=0; i<old_buckets_n; i++){
+        HTBucket *bucket = old_buckets + i;
+        HTEntry *entry, *next;
+        for(entry = bucket->head; entry; entry = next){
+            next = entry->next;
+            push_on_bucket(table, entry->hashcode, entry);
+        }
+    }
+    deallocate(old_buckets);
+  exit:
+    return err;
+}
+
+/** Adjust the number of buckets so the table is neither too full nor too empty.
+ * The table is unmodified if adjusting fails.
+ *
+ * @param table hash table
+ * @param buckets_min minimum number of buckets (use default if 0 or negative)
+ * @return 0 on success, error code otherwise
+ */
+int HashTable_adjust(HashTable *table, int buckets_min){
+    int buckets_n = 0;
+    int err = 0;
+    if(buckets_min <= 0) buckets_min = HT_BUCKETS_N;
+    if(table->entry_count >= table->buckets_n){
+        // The table is dense - expand it.
+        buckets_n = 2 * table->buckets_n;
+    } else if((table->buckets_n > buckets_min) &&
+              (4 * table->entry_count < table->buckets_n)){
+        // The table is more than minimum size and sparse - shrink it.
+        buckets_n = 2 * table->entry_count;
+        if(buckets_n < buckets_min) buckets_n = buckets_min;
+    }
+    if(buckets_n){
+        err = HashTable_set_buckets_n(table, buckets_n);
+    }
+    return err;
+}
+
+/** Allocate a new entry for a given value.
+ *
+ * @param value to put in the entry
+ * @return entry, or 0 on failure
+ */
+HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value){
+    HTEntry *z = ALLOCATE(HTEntry);
+    if(z){
+        z->hashcode = hashcode;
+        z->key = key;
+        z->value = value;
+    }
+    return z;
+}
+
+/** Free an entry.
+ *
+ * @param z entry to free
+ */
+inline void HTEntry_free(HTEntry *z){
+    if(z){
+        deallocate(z);
+    }
+}
+
+/** Free an entry in a hashtable.
+ * The table's entry_free_fn is used is defined, otherwise 
+ * the HTEntry itself is freed.
+ *
+ * @param table hashtable
+ * @param entry to free
+ */
+inline void HashTable_free_entry(HashTable *table, HTEntry *entry){
+    if(!entry)return;
+    if(table && table->entry_free_fn){
+        table->entry_free_fn(table, entry);
+    } else {
+        HTEntry_free(entry);
+    }
+}
+
+/** Get the first entry satisfying a test from the bucket for the
+ * given hashcode.
+ *
+ * @param table to look in
+ * @param hashcode indicates the bucket
+ * @param test_fn test to apply to elements
+ * @param arg first argument to calls to test_fn
+ * @return entry found, or 0
+ */
+inline HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
+                                     TableTestFn *test_fn, TableArg arg){
+    HTBucket *bucket;
+    HTEntry *entry = 0;
+    HTEntry *next;
+
+    bucket = get_bucket(table, hashcode);
+    for(entry = bucket->head; entry; entry = next){
+        next = entry->next;
+        if(test_fn(arg, table, entry)){
+            break;
+        }
+    }
+    return entry;
+}
+
+/** Test hashtable keys for equality.
+ * Uses the table's key_equal_fn if defined, otherwise pointer equality.
+ *
+ * @param key1 key to compare
+ * @param key2 key to compare
+ * @return 1 if equal, 0 otherwise
+ */
+inline int HashTable_key_equal(HashTable *table, void *key1, void *key2){
+    return (table->key_equal_fn ? table->key_equal_fn(key1, key2) : key1==key2);
+}
+
+/** Compute the hashcode of a hashtable key.
+ * The table's key_hash_fn is used if defined, otherwise the address of
+ * the key is hashed.
+ *
+ * @param table hashtable
+ * @param key to hash
+ * @return hashcode
+ */
+inline Hashcode HashTable_key_hash(HashTable *table, void *key){
+    return (table->key_hash_fn ? table->key_hash_fn(key) : hash_ul((unsigned long)key));
+}
+
+/** Test if an entry has a given key.
+ *
+ * @param arg containing key to test for
+ * @param table the entry is in
+ * @param entry to test
+ * @return 1 if the entry has the key, 0 otherwise
+ */
+static inline int has_key(TableArg arg, HashTable *table, HTEntry *entry){
+    return HashTable_key_equal(table, arg.ptr, entry->key);
+}
+
+/** Get an entry with a given key.
+ *
+ * @param table to search
+ * @param key to look for
+ * @return entry if found, null otherwise
+ */
+#if 0
+inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
+    TableArg arg = { ptr: key };
+    return HashTable_find_entry(table, HashTable_key_hash(table, key), has_key, arg);
+}
+#else
+inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
+    Hashcode hashcode;
+    HTBucket *bucket;
+    HTEntry *entry = 0;
+    HTEntry *next;
+
+    hashcode = HashTable_key_hash(table, key);
+    bucket = get_bucket(table, hashcode);
+    for(entry = bucket->head; entry; entry = next){
+        next = entry->next;
+        if(HashTable_key_equal(table, key, entry->key)){
+            break;
+        }
+    }
+    return entry;
+}
+#endif
+
+/** Get the value of an entry with a given key.
+ *
+ * @param table to search
+ * @param key to look for
+ * @return value if an entry was found, null otherwise
+ */
+inline void * HashTable_get(HashTable *table, void *key){
+    HTEntry *entry = HashTable_get_entry(table, key);
+    return (entry ? entry->value : 0);
+}
+
+/** Print the buckets in a table.
+ *
+ * @param table to print
+ */
+void show_buckets(HashTable *table, IOStream *io){
+    int i,j ;
+    IOStream_print(io, "entry_count=%d buckets_n=%d\n", table->entry_count, table->buckets_n);
+    for(i=0; i<table->buckets_n; i++){
+        if(0 || table->buckets[i].count>0){
+            IOStream_print(io, "bucket %3d %3d %10p ", i,
+                        table->buckets[i].count,
+                        table->buckets[i].head);
+            for(j = table->buckets[i].count; j>0; j--){
+                IOStream_print(io, "+");
+            }
+            IOStream_print(io, "\n");
+        }
+    }
+    HashTable_print(table, io); 
+}
+    
+/** Print an entry in a table.
+ *
+ * @param entry to print
+ * @param arg a pointer to an IOStream to print to
+ * @return 0
+ */
+static int print_entry(TableArg arg, HashTable *table, HTEntry *entry){
+    IOStream *io = (IOStream*)arg.ptr;
+    IOStream_print(io, " b=%4lx h=%08lx i=%08lx |-> e=%8p k=%8p v=%8p\n",
+                entry->hashcode % table->buckets_n,
+                entry->hashcode,
+                entry->index,
+                entry, entry->key, entry->value);
+    return 0;
+}
+
+/** Print a hash table.
+ *
+ * @param table to print
+ */
+void HashTable_print(HashTable *table, IOStream *io){
+    IOStream_print(io, "{\n");
+    HashTable_map(table, print_entry, (TableArg){ ptr: io });
+    IOStream_print(io, "}\n");
+}
+/*==========================================================================*/
+
+/** Get the next entry id to use for a table.
+ *
+ * @param table hash table
+ * @return non-zero entry id
+ */
+static inline unsigned long get_next_id(HashTable *table){
+    unsigned long id;
+
+    if(table->next_id == 0){
+        table->next_id = 1;
+    }
+    id = table->next_id++;
+    return id;
+}
+
+/** Add an entry to the bucket for the
+ * given hashcode.
+ *
+ * @param table to insert in
+ * @param hashcode indicates the bucket
+ * @param key to add an entry for
+ * @param value to add an entry for
+ * @return entry on success, 0 on failure
+ */
+inline HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value){
+    HTEntry *entry = HTEntry_new(hashcode, key, value);
+    if(entry){
+        entry->index = get_next_id(table);
+        push_on_bucket(table, hashcode, entry);
+        table->entry_count++;
+    }
+    return entry;
+}
+
+/** Move the front entry for a bucket to the correct point in the bucket order as
+ * defined by the order function. If this is called every time a new entry is added
+ * the bucket will be maintained in sorted order.
+ *
+ * @param table to modify
+ * @param hashcode indicates the bucket
+ * @param order entry comparison function
+ * @return 0 if an entry was moved, 1 if not
+ */
+int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order){
+    HTEntry *new_entry = NULL, *prev = NULL, *entry = NULL;
+    HTBucket *bucket;
+    int err = 1;
+
+    bucket = get_bucket(table, hashcode);
+    new_entry = bucket->head;
+    if(!new_entry || !new_entry->next) goto exit;
+    for(entry = new_entry->next; entry; prev = entry, entry = entry->next){
+        if(order(new_entry, entry) <= 0) break;
+    }
+    if(prev){
+        err = 0;
+        bucket->head = new_entry->next; 
+        new_entry->next = entry;
+        prev->next = new_entry;
+    }
+  exit:
+    return err;
+}
+
+/** Add an entry to a hashtable.
+ * The entry is added to the bucket for its key's hashcode.
+ *
+ * @param table to insert in
+ * @param key to add an entry for
+ * @param value to add an entry for
+ * @return entry on success, 0 on failure
+ */
+inline HTEntry * HashTable_add(HashTable *table, void *key, void *value){
+    return HashTable_add_entry(table, HashTable_key_hash(table, key), key, value);
+}
+
+
+/** Remove entries satisfying a test from the bucket for the
+ * given hashcode. 
+ *
+ * @param table to remove from
+ * @param hashcode indicates the bucket
+ * @param test_fn test to apply to elements
+ * @param arg first argument to calls to test_fn
+ * @return number of entries removed
+ */
+inline int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
+                                 TableTestFn *test_fn, TableArg arg){
+    HTBucket *bucket;
+    HTEntry *entry, *prev = 0, *next;
+    int removed_count = 0;
+
+    bucket = get_bucket(table, hashcode);
+    for(entry = bucket->head; entry; entry = next){
+        next = entry->next;
+        if(test_fn(arg, table, entry)){
+            if(prev){
+                prev->next = next;
+            } else {
+                bucket->head = next;
+            }
+            bucket->count--;
+            table->entry_count--;
+            removed_count++;
+            HashTable_free_entry(table, entry);
+            entry = 0;
+        }
+        prev = entry;
+    }
+    return removed_count;
+}
+
+/** Remove entries with a given key. 
+ *
+ * @param table to remove from
+ * @param key of entries to remove
+ * @return number of entries removed
+ */
+inline int HashTable_remove(HashTable *table, void *key){
+#if 1
+    Hashcode hashcode;
+    HTBucket *bucket;
+    HTEntry *entry, *prev = 0, *next;
+    int removed_count = 0;
+
+    hashcode = HashTable_key_hash(table, key);
+    bucket = get_bucket(table, hashcode);
+    for(entry = bucket->head; entry; entry = next){
+        next = entry->next;
+        if(HashTable_key_equal(table, key, entry->key)){
+            if(prev){
+                prev->next = next;
+            } else {
+                bucket->head = next;
+            }
+            bucket->count--;
+            table->entry_count--;
+            removed_count++;
+            HashTable_free_entry(table, entry);
+            entry = 0;
+        }
+        prev = entry;
+    }
+    return removed_count;
+#else
+    return HashTable_remove_entry(table, HashTable_key_hash(table, key),
+                                 has_key, (TableArg){ ptr: key});
+#endif
+}
+
+/** Remove (and free) all the entries in a bucket.
+ *
+ * @param bucket to clear
+ */
+static inline void bucket_clear(HashTable *table, HTBucket *bucket){
+    HTEntry *entry, *next;
+
+    for(entry = bucket->head; entry; entry = next){
+        next = entry->next;
+        HashTable_free_entry(table, entry);
+    }
+    bucket->head = 0;
+    table->entry_count -= bucket->count;
+    bucket->count = 0;
+}
+
+/** Remove (and free) all the entries in a table.
+ *
+ * @param table to clear
+ */
+void HashTable_clear(HashTable *table){
+    int i, n = table->buckets_n;
+
+    for(i=0; i<n; i++){
+        bucket_clear(table, table->buckets + i);
+    }
+}
diff --git a/tools/libxutil/hash_table.h b/tools/libxutil/hash_table.h
new file mode 100644 (file)
index 0000000..6d7e76f
--- /dev/null
@@ -0,0 +1,295 @@
+/* $Id: hash_table.h,v 1.1 2004/03/30 16:21:26 mjw Exp $ */
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _XEN_LIB_HASH_TABLE_H_
+#define _XEN_LIB_HASH_TABLE_H_
+
+#include "iostream.h"
+
+typedef unsigned long Hashcode;
+
+/** Type used to pass parameters to table functions. */
+typedef union TableArg {
+    unsigned long ul;
+    void *ptr;
+} TableArg;
+
+/** An entry in a bucket list. */
+typedef struct HTEntry {
+    /** Hashcode of the entry's key. */
+    Hashcode hashcode;
+    /** Identifier for this entry in the table. */
+    int index;
+    /** The key for this entry. */
+    void *key;
+    /** The value in this entry. */
+    void *value;
+    /** The next entry in the list. */
+    struct HTEntry *next;
+} HTEntry;
+
+/** A bucket in a rule table. */
+typedef struct HTBucket {
+    /** Number of entries in the bucket. */
+    int count;
+    /** First entry in the bucket (may be null). */
+    HTEntry *head;
+} HTBucket;
+
+/** Default number of buckets in a hash table.
+ * You want enough buckets so the lists in the buckets will typically be short.
+ * It's a good idea if this is prime, since that will help to spread hashcodes
+ * around the table.
+ */
+//#define HT_BUCKETS_N 1
+//#define HT_BUCKETS_N 3
+//#define HT_BUCKETS_N 7
+//#define HT_BUCKETS_N 17
+//#define HT_BUCKETS_N 97
+//#define HT_BUCKETS_N 211
+//#define HT_BUCKETS_N 401
+#define HT_BUCKETS_N 1021
+
+typedef struct HashTable HashTable;
+
+/** Type for a function used to select table entries. */
+typedef int TableTestFn(TableArg arg, HashTable *table, HTEntry *entry);
+
+/** Type for a function to map over table entries. */
+typedef int TableMapFn(TableArg arg, HashTable *table, HTEntry *entry);
+
+/** Type for a function to free table entries. */
+typedef void TableFreeFn(HashTable *table, HTEntry *entry);
+
+/** Type for a function to hash table keys. */
+typedef Hashcode TableHashFn(void *key);
+
+/** Type for a function to test table keys for equality. */
+typedef int TableEqualFn(void *key1, void *key2);
+
+/** Type for a function to order table entries. */
+typedef int TableOrderFn(HTEntry *e1, HTEntry *e2);
+
+/** General hash table.
+ * A hash table with a list in each bucket.
+ * Functions can be supplied for freeing entries, hashing keys, and comparing keys.
+ * These all default to 0, when default behaviour treating keys as integers is used.
+ */
+struct HashTable {
+    /** Flag indicating whether the table has been initialised. */
+    int init_done;
+    /** Next value for the id field in inserted rules. */
+    unsigned long next_id;
+    /** Number of buckets in the bucket array. */
+    int buckets_n;
+    /** Array of buckets, each with its own list. */
+    HTBucket *buckets;
+    /** Number of entries in the table. */
+    int entry_count;
+    /** Function to free keys and values in entries. */
+    TableFreeFn *entry_free_fn;
+    /** Function to hash keys. */
+    TableHashFn *key_hash_fn;
+    /** Function to compare keys for equality. */
+    TableEqualFn *key_equal_fn;
+    /** Place for the user of the table to hang extra data. */
+    void *user_data;
+};
+
+extern HashTable *HashTable_new(int bucket_n);
+extern void HashTable_free(HashTable *table);
+extern HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value);
+extern void HTEntry_free(HTEntry *entry);
+extern int HashTable_set_bucket_n(HashTable *table, int bucket_n);
+extern void HashTable_clear(HashTable *table);
+extern HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value);
+extern HTEntry * HashTable_get_entry(HashTable *table, void *key);
+extern HTEntry * HashTable_add(HashTable *table, void *key, void *value);
+extern void * HashTable_get(HashTable *table, void *key);
+extern int HashTable_remove(HashTable *table, void *key);
+extern HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
+                                      TableTestFn *test_fn, TableArg arg);
+extern int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
+                                   TableTestFn *test_fn, TableArg arg);
+//extern int HashTable_map(HashTable *table, TableMapFn *map_fn, TableArg arg);
+extern void HashTable_print(HashTable *table, IOStream *out);
+extern int HashTable_set_buckets_n(HashTable *table, int buckets_n);
+extern int HashTable_adjust(HashTable *table, int buckets_min);
+extern void pseudo_des(unsigned long *pleft, unsigned long *pright);
+extern Hashcode hash_string(char *s);
+
+extern int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order);
+
+/** Control whether to use hashing based on DES or simple
+ * hashing. DES hashing is `more random' but much more expensive.
+ */
+#define HASH_PSEUDO_DES 0
+
+/** Hash a long using a quick and dirty linear congruential random number generator.
+ *  See `Numerical Recipes in C', Chapter 7, "An Even Quicker Generator".
+ *
+ * @param a value to hash
+ * @return hashed input
+ */
+static inline unsigned long lcrng_hash(unsigned long a){
+    return (1664525L * a + 1013904223L);
+}
+
+/** Hash an unsigned long.
+ *
+ * @param a input to hash
+ * @return hashcode
+ */
+static inline Hashcode hash_ul(unsigned long a){
+#if HASH_PSEUDO_DES
+    unsigned long left = a;
+    unsigned long right = 0L;
+    pseudo_des(&left, &right);
+    return right;
+#else
+    a = lcrng_hash(a);
+    a = lcrng_hash(a);
+    return a;
+#endif
+}
+
+/** Hash two unsigned longs together.
+ *
+ * @param a input to hash
+ * @param b input to hash
+ * @return hashcode
+ */
+static inline Hashcode hash_2ul(unsigned long a, unsigned long b){
+#if HASH_PSEUDO_DES
+    unsigned long left = a;
+    unsigned long right = b;
+    pseudo_des(&left, &right);
+    return right;
+#else
+    a = lcrng_hash(a);
+    a ^= b;
+    a = lcrng_hash(a);
+    return a;
+#endif
+}
+
+/** Hash a hashcode and an unsigned long together.
+ *
+ * @param a input hashcode
+ * @param b input to hash
+ * @return hashcode
+ */
+static inline Hashcode hash_hul(Hashcode a, unsigned long b){
+#if HASH_PSEUDO_DES
+    unsigned long left = a;
+    unsigned long right = b;
+    pseudo_des(&left, &right);
+    return right;
+#else
+    a ^= b;
+    a = lcrng_hash(a);
+    return a;
+#endif
+}
+
+/** Macro to declare variables for HashTable_for_each() to use.
+ *
+ * @param entry variable that is set to entries in the table
+ */
+#define HashTable_for_decl(entry) \
+  HashTable *_var_table; \
+  HTBucket *_var_bucket; \
+  HTBucket *_var_end; \
+  HTEntry *_var_next; \
+  HTEntry *entry
+
+/** Macro to iterate over the entries in a hashtable.
+ * Must be in a scope where HashTable_for_decl() has been used to declare
+ * variables for it to use.
+ * The variable 'entry' is iterated over entries in the table.
+ * The code produced is syntactically a loop, so it must be followed by
+ * a loop body, typically some statements in braces:
+ * HashTable_for_each(entry, table){ ...loop body... }
+ *
+ * HashTable_for_each() and HashTable_for_decl() cannot be used for nested
+ * loops as variables will clash.
+ *
+ * @note The simplest way to code a direct loop over the entries in a hashtable
+ * is to use a loop over the buckets, with a nested loop over the entries
+ * in a bucket. Using this approach in a macro means the macro contains
+ * an opening brace, and calls to it must be followed by 2 braces!
+ * To avoid this the code has been restructured so that it is a for loop.
+ * So that statements could be used in the test expression of the for loop,
+ * we have used the gcc statement expression extension ({ ... }).
+ *
+ * @param entry variable to iterate over the entries
+ * @param table to iterate over (non-null)
+ */
+#define HashTable_for_each(entry, table) \
+  _var_table = table; \
+  _var_bucket = _var_table->buckets; \
+  _var_end = _var_bucket + _var_table->buckets_n; \
+  for(entry=0, _var_next=0; \
+      ({ if(_var_next){ \
+             entry = _var_next; \
+             _var_next = entry->next; \
+          } else { \
+             while(_var_bucket < _var_end){ \
+                 entry = _var_bucket->head; \
+                 _var_bucket++; \
+                 if(entry){ \
+                      _var_next = entry->next; \
+                      break; \
+                 } \
+             } \
+          }; \
+         entry; }); \
+      entry = _var_next )
+
+/** Map a function over the entries in a table.
+ * Mapping stops when the function returns a non-zero value.
+ * Uses the gcc statement expression extension ({ ... }).
+ *
+ * @param table to map over
+ * @param fn function to apply to entries
+ * @param arg first argument to call the function with
+ * @return 0 if fn always returned 0, first non-zero value otherwise
+ */
+#define HashTable_map(table, fn, arg) \
+  ({ HashTable_for_decl(_var_entry); \
+    TableArg _var_arg = arg; \
+    int _var_value = 0; \
+    HashTable_for_each(_var_entry, table){ \
+        if((_var_value = fn(_var_arg, _var_table, _var_entry))) break; \
+    } \
+    _var_value; })
+
+/** Cast x to the type for a key or value in a hash table.
+ * This avoids compiler warnings when using short integers
+ * as keys or values (especially on 64-bit platforms).
+ */
+#define HKEY(x) ((void*)(unsigned long)(x))
+
+/** Cast x from the type for a key or value in a hash table.
+ * to an unsigned long. This avoids compiler warnings when using
+ * short integers as keys or values (especially on 64-bit platforms).
+ */
+#define HVAL(x) ((unsigned long)(x))
+
+#endif /* !_XEN_LIB_HASH_TABLE_H_ */
diff --git a/tools/libxutil/iostream.c b/tools/libxutil/iostream.c
new file mode 100644 (file)
index 0000000..e998083
--- /dev/null
@@ -0,0 +1,37 @@
+#include "iostream.h"
+#include "sys_string.h"
+
+/** Print on a stream, like vfprintf().
+ *
+ * @param stream to print to
+ * @param format for the print (as fprintf())
+ * @param args arguments to print
+ * @return result code from the print
+ */
+int IOStream_vprint(IOStream *stream, const char *format, va_list args){
+  char buffer[1024];
+  int k = sizeof(buffer), n;
+
+  n = vsnprintf(buffer, k, (char*)format, args);
+  if(n < 0 || n > k ){
+      n = k;
+  }
+  n = IOStream_write(stream, buffer, n);
+  return n;
+}
+
+/** Print on a stream, like fprintf().
+ *
+ * @param stream to print to
+ * @param format for the print (as fprintf())
+ * @return result code from the print
+ */
+int IOStream_print(IOStream *stream, const char *format, ...){
+  va_list args;
+  int result = -1;
+
+  va_start(args, format);
+  result = IOStream_vprint(stream, format, args);
+  va_end(args);
+  return result;
+}
diff --git a/tools/libxutil/iostream.h b/tools/libxutil/iostream.h
new file mode 100644 (file)
index 0000000..5dbe14a
--- /dev/null
@@ -0,0 +1,243 @@
+#ifndef _XC_LINUX_SAVE_H_
+#define _XC_LINUX_SAVE_H_
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __KERNEL__
+#include <linux/errno.h>
+#else
+#include <errno.h>
+#endif
+
+#include "allocate.h"
+
+/** End of input return value. */
+#define IOSTREAM_EOF -1
+
+/** An input/output abstraction.
+ */
+typedef struct IOStream IOStream;
+
+/** Record of the functions to use for operations on an
+ * IOStream implementation.
+ */
+typedef struct IOMethods {
+    /** Read function.  Called with the user data, buffer to read into
+     * and number of bytes to read.  Must return number of bytes read
+     * on success, less than zero on error.
+     */
+    int (*read)(IOStream *stream, void *buf, size_t n);
+
+    /** Write function. Called with user data, buffer to write and
+     * number of bytes to write. Must return number of bytes written on
+     * success, less than zero otherwise.
+     */
+    int (*write)(IOStream *stream, const void *buf, size_t n);
+
+    int (*flush)(IOStream *s);
+
+    int (*error)(IOStream *s);
+
+    int (*close)(IOStream *s);
+
+    void (*free)(IOStream *s);
+
+    void (*lock)(IOStream *s);
+    void (*unlock)(IOStream *s);
+
+} IOMethods;
+
+/** Abstract i/o object.
+ */
+struct IOStream {
+    /** Methods to use to implement operations. */
+    const IOMethods *methods;
+    /** Private state for the implementation. */
+    const void *data;
+    /** Flag indicating whether the stream is closed. */
+    int closed;
+    /** Number of bytes written. */
+    int written;
+    /** Number of bytes read. */
+    int read;
+};
+
+
+/** IOStream version of stdin. */
+extern IOStream *iostdin;
+
+/** IOStream version of stdout, */
+extern IOStream *iostdout;
+
+/** IOStream version of stderr. */
+extern IOStream *iostderr;
+
+extern int IOStream_print(IOStream *io, const char *format, ...);
+extern int IOStream_vprint(IOStream *io, const char *format, va_list args);
+
+/** Read from a stream.
+ *
+ * @param stream input
+ * @param buf where to put input
+ * @param n number of bytes to read
+ * @return if ok, number of bytes read, otherwise negative error code
+ */
+static inline int IOStream_read(IOStream *stream, void *buf, size_t n){
+    int result = 0;
+    if(stream->closed) goto exit;
+    if(!stream->methods || !stream->methods->read){
+        result = -EINVAL;
+        goto exit;
+    }
+    result = stream->methods->read(stream, buf, n);
+    if(result > 0){
+        stream->read += result;
+    }
+  exit:
+    return result;
+}
+
+/** Write to a stream.
+ *
+ * @param stream input
+ * @param buf where to put input
+ * @param n number of bytes to write
+ * @return if ok, number of bytes read, otherwise negative error code
+ */
+static inline int IOStream_write(IOStream *stream, const void *buf, size_t n){
+    int result = 0;
+    if(stream->closed) goto exit;
+    if(!stream->methods || !stream->methods->write){
+        result = -EINVAL;
+        goto exit;
+    }
+    result = stream->methods->write(stream, buf, n);
+    if(result > 0){
+        stream->written += result;
+    }
+  exit:
+    return result;
+}
+
+/** Flush the stream.
+ *
+ * @param stream stream
+ * @return 0 on success, IOSTREAM_EOF otherwise
+ */
+static inline int IOStream_flush(IOStream *stream){
+    int result = 0;
+    if(stream->closed){
+        result = IOSTREAM_EOF;
+    } else if(stream->methods->flush){
+        result = stream->methods->flush(stream);
+        if(result < 0) result = IOSTREAM_EOF;
+    }
+    return result;
+}
+
+/** Check whether the stream has an error.
+ *
+ * @param stream to check
+ * @return 1 for error, 0 otherwise
+ */
+static inline int IOStream_error(IOStream *stream){
+    int err = 0;
+    if(stream->methods && stream->methods->error){
+       err = stream->methods->error(stream);
+    }
+    return err;
+}
+
+/** Close the stream.
+ *
+ * @param stream to close
+ * @return 1 for error, 0 otherwise
+ */
+static inline int IOStream_close(IOStream *stream){
+    int err = 1;
+    if(stream->methods && stream->methods->close){
+        err = stream->methods->close(stream);
+    }
+    return err;
+}
+
+/** Test if the stream has been closed.
+ *
+ * @param stream to check
+ * @return 1 if closed, 0 otherwise
+ */
+static inline int IOStream_is_closed(IOStream *stream){
+  return stream->closed;
+}
+
+/** Free the memory used by the stream.
+ *
+ * @param stream to free
+ */
+static inline void IOStream_free(IOStream *stream){
+  if(stream->methods && stream->methods->free){
+    stream->methods->free(stream);
+  }
+  *stream = (IOStream){};
+  deallocate(stream);
+}
+
+
+/** Print a character to a stream, like fputc().
+ *
+ * @param stream to print to
+ * @param c character to print
+ * @return result code from the print
+ */
+static inline int IOStream_putc(IOStream *stream, int c){
+    int err;
+    unsigned char b = (unsigned char)c;
+    err = IOStream_write(stream, &b, 1);
+    if(err < 1){
+        err = IOSTREAM_EOF;
+    } else {
+        err = b;
+    }
+    return err;
+}
+
+/** Read from a stream, like fgetc().
+ *
+ * @param stream to read from
+ * @return IOSTREAM_EOF on error, character read otherwise
+ */
+static inline int IOStream_getc(IOStream *stream){
+    int err, rc;
+    unsigned char b;
+
+    err = IOStream_read(stream, &b, 1);
+    if(err < 1){
+        rc = IOSTREAM_EOF;
+    } else {
+        rc = b;
+    }
+    return rc;
+}
+
+/** Get number of bytes read.
+ *
+ * @param stream to get from
+ * @return number of bytes read
+ */
+static inline int IOStream_get_read(IOStream *stream){
+    return stream->read;
+}
+
+/** Get number of bytes written.
+ *
+ * @param stream to get from
+ * @return number of bytes written
+ */
+static inline int IOStream_get_written(IOStream *stream){
+    return stream->written;
+}
+
+
+#endif /* ! _XC_LINUX_SAVE_H_ */
diff --git a/tools/libxutil/kernel_stream.c b/tools/libxutil/kernel_stream.c
new file mode 100644 (file)
index 0000000..345b048
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/** @file
+ * An IOStream implementation using printk() for output.
+ * Input is not implemented.
+ */
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "kernel_stream.h"
+#include "allocate.h"
+
+/** Number of characters in the output buffer.
+ * The kernel uses 1024 for printk, so that should suffice.
+ */
+#define BUF_N 1024
+
+/** State for a kernel stream. */
+typedef struct KernelData {
+    /** Stream lock. We need a lock to serialize access to the stream. */
+    spinlock_t lock;
+    /** Saved flags for locking. */
+    unsigned long flags;
+    /** Size of the output buffer. */
+    int buf_n;
+    /** Output buffer. */
+    char buf[BUF_N];
+} KernelData;
+
+static int kernel_write(IOStream *s, const char *msg, int n);
+static void kernel_free(IOStream *s);
+static void kernel_stream_lock(IOStream *s);
+static void kernel_stream_unlock(IOStream *s);
+
+/** Methods for a kernel stream. Output only. */
+static const IOMethods kernel_methods = {
+  write:  kernel_write,
+  free:   kernel_free,
+  lock:   kernel_stream_lock,
+  unlock: kernel_stream_unlock,
+};
+
+/** Shared state for kernel streams.
+ * All implementations write using printk, so we can use
+ * shared state and avoid allocating it.
+ */
+static const KernelData kernel_data = {
+  lock: SPIN_LOCK_UNLOCKED,
+  flags: 0,
+  buf_n: BUF_N,
+};
+
+/** Stream for kernel printk. */
+static IOStream iokernel = {
+    methods: &kernel_methods,
+    data:    &kernel_data,
+};
+
+/** Stream for kernel printk. */
+IOStream *iostdout = &iokernel;
+
+/** Stream for kernel printk. */
+IOStream *iostdin = &iokernel;
+
+/** Stream for kernel printk. */
+IOStream *iostderr = &iokernel;
+
+/** Get an output-only stream implementation using
+ * printk(). The stream uses static storage, and must not be freed.
+ *
+ * @return kernel stream
+ */
+IOStream get_stream_kernel(void){
+  return iokernel;
+}
+
+/** Obtain the lock on the stream state.
+ *
+ * @param kdata stream state
+ */
+static inline void KernelData_lock(KernelData *kdata){
+  spin_lock_irqsave(&kdata->lock, kdata->flags);
+}
+
+/** Release the lock on the stream state.
+ *
+ * @param kdata stream state
+ */
+static inline void KernelData_unlock(KernelData *kdata){
+  spin_unlock_irqrestore(&kdata->lock, kdata->flags);
+}
+
+/** Get the stream state.
+ *
+ * @param s kernel stream
+ * @return stream state
+ */
+static inline KernelData *get_kernel_data(IOStream *s){
+  return (KernelData*)s->data;
+}
+
+/** Obtain the lock on the stream state.
+ *
+ * @param s stream
+ */
+void kernel_stream_lock(IOStream *s){
+    KernelData_lock(get_kernel_data(s));
+}
+
+/** Release the lock on the stream state.
+ *
+ * @param s stream
+ */
+void kernel_stream_unlock(IOStream *s){
+    KernelData_unlock(get_kernel_data(s));
+}
+
+/** Write to a kernel stream.
+ *
+ * @param stream kernel stream
+ * @param format print format
+ * @param args print arguments
+ * @return result of the print
+ */
+static int kernel_write(IOStream *stream, const char *buf, int n){
+  KernelData *kdata = get_kernel_data(stream);
+  int k;
+  k = kdata->buf_n - 1;
+  if(n < k) k = n;
+  memcpy(kdata->buf, buf, k);
+  kdata->buf[k] = '\0'
+  printk(kdata->buf);
+  return k;
+}
+
+/** Free a kernel stream.
+ * Frees the internal state of the stream.
+ * Do not call this unless the stream was dynamically allocated.
+ * Do not call this on a stream returned from get_stream_kernel().
+ *
+ * @param io stream to free
+ */
+static void kernel_free(IOStream *io){
+  KernelData *kdata;
+  if(io == &iokernel) return;
+  kdata = get_kernel_data(io);
+  zero(kdata, sizeof(*kdata));
+  deallocate(kdata);
+}
+#endif /* __KERNEL__ */
+
+
+
+
diff --git a/tools/libxutil/kernel_stream.h b/tools/libxutil/kernel_stream.h
new file mode 100644 (file)
index 0000000..be370f2
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _XEN_LIB_KERNEL_STREAM_H_
+#define _XEN_LIB_KERNEL_STREAM_H_
+
+#ifdef __KERNEL__
+#include "iostream.h"
+
+extern IOStream get_stream_kernel(void);
+#define get_stream_stdout get_stream_kernel
+
+#endif /* __KERNEL__ */
+#endif /* !_XEN_LIB_KERNEL_STREAM_H_ */
diff --git a/tools/libxutil/lexis.c b/tools/libxutil/lexis.c
new file mode 100644 (file)
index 0000000..26d2ec4
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or  (at your option) any later version. This library is 
+ * distributed in the  hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+/** @file
+ * Lexical analysis.
+ */
+
+#include "sys_string.h"
+#include "lexis.h"
+#include <errno.h>
+
+/** Check if a value lies in a (closed) range.
+ *
+ * @param x value to test
+ * @param lo low end of the range
+ * @param hi high end of the range
+ * @return 1 if x is in the interval [lo, hi], 0 otherwise
+ */
+inline static int in_range(int x, int lo, int hi){
+    return (lo <= x) && (x <= hi);
+}
+
+/** Determine if a string is an (unsigned) decimal number.
+ * 
+ * @param s pointer to characters to test
+ * @param n length of string
+ * @return 1 if s is a decimal number, 0 otherwise.
+ */
+int is_decimal_number(const char *s, int n){
+    int i;
+    if(n <= 0)return 0;
+    for(i = 0; i < n; i++){
+        if(!in_decimal_digit_class(s[i])) return 0;
+    }
+    return 1;
+}
+
+/** Determine if a string is a hex number.
+ * Hex numbers are 0, or start with 0x or 0X followed
+ * by a non-zero number of hex digits (0-9,a-f,A-F).
+ * 
+ * @param s pointer to characters to test
+ * @param n length of string
+ * @return 1 if s is a hex number, 0 otherwise.
+ */
+int is_hex_number(const char *s, int n){
+    int i;
+    if(n <= 0) return 0;
+    if(n == 1){
+        return s[0]=='0';
+    }
+    if(n <= 3) return 0;
+    if(s[0] != '0' || (s[1] != 'x' && s[1] != 'X')) return 0;
+    for(i = 2; i < n; i++){
+        if(!in_hex_digit_class(s[i])) return 0;
+    }
+    return 1;
+}
+
+/** Test if a string matches a keyword.
+ * The comparison is case-insensitive.
+ * The comparison fails if either argument is null.
+ *
+ * @param s string
+ * @param k keyword
+ * @return 1 if they match, 0 otherwise
+ */
+int is_keyword(const char *s, const char *k){
+  return s && k && !strcasecmp(s, k);
+}
+
+/** Test if a string matches a character.
+ *
+ * @param s string
+ * @param c character (non-null)
+ * @return 1 if s contains exactly c, 0 otherwise
+ */
+int is_keychar(const char *s, char c){
+  return c && (s[0] == c) && !s[1];
+}
diff --git a/tools/libxutil/lexis.h b/tools/libxutil/lexis.h
new file mode 100644 (file)
index 0000000..7d8fe7b
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or  (at your option) any later version. This library is 
+ * distributed in the  hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef _SP_LEXIS_H_
+#define _SP_LEXIS_H_
+
+#include "sys_string.h"
+#include "sys_ctype.h"
+
+/** @file
+ * Lexical analysis.
+ */
+
+/** Class of characters treated as space. */
+#define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 })
+
+/** Class of separator characters. */
+#define sep_class "{}()<>[]@!;"
+
+#define comment_class "#"
+
+/** Determine if a character is in a given class.
+ * 
+ * @param c character to test
+ * @param s null-terminated string of characters in the class
+ * @return 1 if c is in the class, 0 otherwise.
+ */
+static inline int in_class(int c, const char *s){
+  return s && (strchr(s, c) != 0);
+}
+
+/** Determine if a character is in the space class.
+ * 
+ * @param c character to test
+ * @return 1 if c is in the class, 0 otherwise.
+ */
+static inline int in_space_class(int c){
+    return in_class(c, space_class);
+}
+
+static inline int in_comment_class(int c){
+    return in_class(c, comment_class);
+}
+
+/** Determine if a character is in the separator class.
+ * Separator characters terminate tokens, and do not need space
+ * to separate them.
+ * 
+ * @param c character to test
+ * @return 1 if c is in the class, 0 otherwise.
+ */
+static inline int in_sep_class(int c){
+    return in_class(c, sep_class);
+}
+
+/** Determine if a character is in the alpha class.
+ * 
+ * @param c character to test
+ * @return 1 if c is in the class, 0 otherwise.
+ */
+static inline int in_alpha_class(int c){
+    return isalpha(c);
+}
+
+/** Determine if a character is in the octal digit class.
+ * 
+ * @param c character to test
+ * @return 1 if c is in the class, 0 otherwise.
+ */
+static inline int in_octal_digit_class(int c){
+    return '0' <= c && c <= '7';
+}
+
+/** Determine if a character is in the decimal digit class.
+ * 
+ * @param c character to test
+ * @return 1 if c is in the class, 0 otherwise.
+ */
+static inline int in_decimal_digit_class(int c){
+    return isdigit(c);
+}
+
+/** Determine if a character is in the hex digit class.
+ * 
+ * @param c character to test
+ * @return 1 if c is in the class, 0 otherwise.
+ */
+static inline int in_hex_digit_class(int c){
+    return isdigit(c) || in_class(c, "abcdefABCDEF");
+}
+
+
+static inline int in_string_quote_class(int c){
+    return in_class(c, "'\"");
+}
+
+static inline int in_printable_class(int c){
+    return ('A' <= c && c <= 'Z')
+        || ('a' <= c && c <= 'z')
+        || ('0' <= c && c <= '9')
+        || in_class(c, "!$%&*+,-./:;<=>?@^_`{|}~");
+}
+
+extern int is_decimal_number(const char *s, int n);
+extern int is_hex_number(const char *s, int n);
+extern int is_keyword(const char *s, const char *k);
+extern int is_keychar(const char *s, char c);
+
+#endif /* !_SP_LEXIS_H_ */
diff --git a/tools/libxutil/lzi_stream.c b/tools/libxutil/lzi_stream.c
new file mode 100644 (file)
index 0000000..0f09734
--- /dev/null
@@ -0,0 +1,590 @@
+/* $Id: lzi_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */
+#define __FILE_ID_INFO "$Id: lzi_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $"
+#include <what.h>
+static char __rcsid[] __attribute__((unused)) = WHAT_ID __FILE_ID_INFO;
+/*
+ * Copyright (C) 2003 Hewlett-Packard Company.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/** @file
+ * An IOStream implementation using LZI to provide compression and decompression.
+ * This is designed to provide compression without output latency.
+ * Flushing an LZI stream flushes all pending data to the underlying stream.
+ * This is essential for stream-based (e.g. networked) applications.
+ *
+ * A compressed data stream is a sequence of blocks.
+ * Each block is the block size followed by the compressed data.
+ * The last block has size zero.
+ * Sizes are 4-byte unsigned in network order.
+ *
+ * This format allows compressed data to be read from a stream without reading
+ * past the logical end of compressed data.
+ *
+ * @author Mike Wray <mike.wray@hpl.hp.com>
+ */
+#ifndef __KERNEL__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "zlib.h"
+
+#include "allocate.h"
+#include "lzi_stream.h"
+#include "file_stream.h"
+#include "marshal.h"
+
+#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] LZI>%s" fmt, __FUNCTION__, ##args)
+#define wprintf(fmt, args...) fprintf(stderr, "[WARN]  LZI>%s" fmt, __FUNCTION__, ##args)
+#define iprintf(fmt, args...) fprintf(stdout, "[INFO]  LZI>%s" fmt, __FUNCTION__, ##args)
+#define eprintf(fmt, args...) fprintf(stderr, "[ERROR] LZI>%s" fmt, __FUNCTION__, ##args)
+
+static int lzi_read(IOStream *s, void *buf, size_t size, size_t count);
+static int lzi_write(IOStream *s, const void *buf, size_t size, size_t count);
+static int lzi_print(IOStream *s, const char *msg, va_list args);
+static int lzi_getc(IOStream *s);
+static int lzi_error(IOStream *s);
+static int lzi_close(IOStream *s);
+static void lzi_free(IOStream *s);
+static int lzi_flush(IOStream *s);
+
+enum {
+    LZI_WRITE = 1,
+    LZI_READ = 2,
+};
+
+/** Methods used by a gzFile* IOStream. */
+static const IOMethods lzi_methods = {
+    read: lzi_read,
+    write: lzi_write,
+    print: lzi_print,
+    getc:  lzi_getc,
+    error: lzi_error,
+    close: lzi_close,
+    free:  lzi_free,
+    flush: lzi_flush,
+};
+
+#define BUFFER_SIZE (512 * 1024)
+
+typedef struct LZIState {
+    z_stream zstream;
+    void *inbuf;
+    uint32_t inbuf_size;
+    void *outbuf;
+    uint32_t outbuf_size;
+    /** Underlying stream for I/O. */
+    IOStream *io;
+    /** Flags. */
+    int flags;
+    /** Error indicator. */
+    int error;
+    int eof;
+    int plain_bytes;
+    int comp_bytes;
+    int zstream_initialized;
+    int flushed;
+} LZIState;
+
+static inline int LZIState_writeable(LZIState *s){
+    return (s->flags & LZI_WRITE) != 0;
+}
+
+static inline int LZIState_readable(LZIState *s){
+    return (s->flags & LZI_READ) != 0;
+}
+
+void LZIState_free(LZIState *z){
+    if(!z) return;
+    if(z->zstream_initialized){
+        if(LZIState_writeable(z)){
+            deflateEnd(&z->zstream);
+        } else if(LZIState_readable(z)){
+            inflateEnd(&z->zstream);
+        }
+    }
+    deallocate(z->inbuf);
+    deallocate(z->outbuf);
+    deallocate(z);
+}
+
+static int mode_flags(const char *mode, int *flags){
+    int err = 0;
+    int r=0, w=0;
+    if(!mode){
+        err = -EINVAL;
+        goto exit;
+    }
+    for(; *mode; mode++){
+        if(*mode == 'w') w = 1;
+        if(*mode == 'r') r = 1;
+    }
+    if(r + w != 1){
+        err = -EINVAL;
+        goto exit;
+    }
+    if(r) *flags |= LZI_READ;
+    if(w) *flags |= LZI_WRITE;
+  exit:
+    return err;
+}
+
+/** Get the stream state.
+ * 
+ * @param s lzi stream
+ * @return stream state.
+ */
+static inline LZIState * lzi_state(IOStream *io){
+    return io->data;
+}
+
+IOStream *lzi_stream_io(IOStream *io){
+    LZIState *s = lzi_state(io);
+    return s->io;
+}
+
+static inline void set_error(LZIState *s, int err){
+    if(err < 0 && !s->error){
+        s->error = err;
+    }
+}
+
+static int zerror(LZIState *s, int err){
+    if(err){
+        //dprintf("> err=%d\n", err);
+        if(err < 0) set_error(s, -EIO);
+    }
+    return s->error;
+}
+
+int lzi_stream_plain_bytes(IOStream *io){
+    LZIState *s = lzi_state(io);
+    return s->plain_bytes;
+}
+
+int lzi_stream_comp_bytes(IOStream *io){
+    LZIState *s = lzi_state(io);
+    return s->comp_bytes;
+}
+
+float lzi_stream_ratio(IOStream *io){
+    LZIState *s = lzi_state(io);
+    float ratio = 0.0;
+    if(s->comp_bytes){
+        ratio = ((float) s->comp_bytes)/((float) s->plain_bytes);
+    }
+    return ratio;
+}
+
+static int alloc(void **p, int n){
+    *p = allocate(n);
+    return (p ? 0 : -ENOMEM);
+}
+
+LZIState * LZIState_new(IOStream *io, int flags){
+    int err = -ENOMEM;
+    int zlevel = Z_BEST_SPEED; // Level 1 compression - fastest.
+    int zstrategy = Z_DEFAULT_STRATEGY;
+    int zwindow = MAX_WBITS;
+    int zmemory = 8;
+    LZIState *z = ALLOCATE(LZIState);
+
+    //dprintf(">\n");
+    if(!z) goto exit;
+    z->io = io;
+    z->flags = flags;
+
+    if(LZIState_writeable(z)){
+        z->outbuf_size = BUFFER_SIZE;
+        /* windowBits is passed < 0 to suppress zlib header */
+        err = deflateInit2(&z->zstream, zlevel, Z_DEFLATED, -zwindow, zmemory, zstrategy);
+        if (err != Z_OK) goto exit;
+        z->zstream_initialized = 1;
+        err = alloc(&z->outbuf, z->outbuf_size);
+        if(err) goto exit;
+        z->zstream.next_out = z->outbuf;
+        z->zstream.avail_out = z->outbuf_size;
+    } else {
+        z->inbuf_size = BUFFER_SIZE;
+        err = alloc(&z->inbuf, z->inbuf_size);
+        if(err) goto exit;
+        ///z->zstream.next_in  = z->inbuf;
+
+        /* windowBits is passed < 0 to tell that there is no zlib header.
+         * Note that in this case inflate *requires* an extra "dummy" byte
+         * after the compressed stream in order to complete decompression and
+         * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
+         * present after the compressed stream.
+         */
+        err = inflateInit2(&z->zstream, -zwindow);
+        if(err != Z_OK) goto exit;
+        z->zstream_initialized = 1;
+    }
+        
+  exit:
+    if(err){
+        LZIState_free(z);
+        z = NULL;
+    }
+    //dprintf("< z=%p\n", z);
+    return z;
+}
+
+int read_block(LZIState *s){
+    int err = 0, k = 0;
+    //dprintf(">\n");
+    if(s->eof) goto exit;
+    err = unmarshal_uint32(s->io, &k);
+    if(err) goto exit;
+    if(k > s->inbuf_size){
+        err = -EINVAL;
+        goto exit;
+    }
+    if(k){
+        err = unmarshal_bytes(s->io, s->inbuf, k);
+        if(err) goto exit;
+    } else {
+        s->eof = 1;
+    }        
+    s->zstream.avail_in = k;
+    s->zstream.next_in = s->inbuf;
+    s->comp_bytes += 4;
+    s->comp_bytes += k;
+  exit:
+    //dprintf("< err=%d\n", err);
+    return err;
+}
+
+int write_block(LZIState *s){
+    int err = 0;
+    int k = ((char*)s->zstream.next_out) - ((char*)s->outbuf);
+    int k2 = s->outbuf_size - s->zstream.avail_out;
+    //dprintf("> k=%d k2=%d\n", k, k2);
+    if(!k) goto exit;
+    err = marshal_uint32(s->io, k);
+    if(err) goto exit;
+    err = marshal_bytes(s->io, s->outbuf, k);
+    if(err) goto exit;
+    s->zstream.next_out = s->outbuf;
+    s->zstream.avail_out = s->outbuf_size;
+    s->comp_bytes += 4;
+    s->comp_bytes += k;
+  exit:
+    //dprintf("< err=%d\n", err);
+    return err;
+}
+
+int write_terminator(LZIState *s){
+    int err = 0;
+    char c = 0;
+    err = marshal_uint32(s->io, 1);
+    if(err) goto exit;
+    err = marshal_bytes(s->io, &c, 1);
+    if(err) goto exit;
+    err = marshal_uint32(s->io, 0);
+    if(err) goto exit;
+    s->comp_bytes += 9;
+  exit:
+    return err;
+}
+
+/** Write to the underlying stream using fwrite();
+ *
+ * @param io destination
+ * @param buf data
+ * @param size size of data elements
+ * @param count number of data elements to write
+ * @return number of data elements written
+ */
+static int lzi_write(IOStream *io, const void *buf, size_t size, size_t count){
+    int err = 0;
+    int n = size * count;
+    LZIState *s = lzi_state(io);
+
+    //dprintf("> buf=%p size=%d count=%d n=%d\n", buf, size, count, n);
+    if(!LZIState_writeable(s)){
+        err = -EINVAL;
+        goto exit;
+    }
+    s->flushed = 0;
+    s->zstream.next_in = (void*)buf;
+    s->zstream.avail_in = n;
+    while(s->zstream.avail_in){
+        if(s->zstream.avail_out == 0){
+            err = write_block(s);
+            if(err) goto exit;
+        }
+        //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
+        //dprintf("> 1 deflate next_in=%p next_out=%p\n", s->zstream.next_in, s->zstream.next_out);
+        err = zerror(s, deflate(&s->zstream, Z_NO_FLUSH));
+        //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
+        //dprintf("> 2 deflate next_in=%p next_out=%p\n", s->zstream.next_in, s->zstream.next_out);
+        if(err) goto exit;
+    }
+    err = n;
+    s->plain_bytes += n;
+    if(size != 1) err /= size;
+  exit:
+    //dprintf("< err=%d\n", err);
+    return err;
+}
+
+
+/** Read from the underlying stream.
+ *
+ * @param io input
+ * @param buf where to put input
+ * @param size size of data elements
+ * @param count number of data elements to read
+ * @return number of data elements read
+ */
+static int lzi_read(IOStream *io, void *buf, size_t size, size_t count){
+    int err, zerr;
+    int n = size * count;
+    LZIState *s = lzi_state(io);
+
+    //dprintf("> size=%d count=%d n=%d\n", size, count, n);
+    if(!LZIState_readable(s)){
+        err = -EINVAL;
+        goto exit;
+    }
+    s->zstream.next_out = buf;
+    s->zstream.avail_out = n;
+    while(s->zstream.avail_out){
+        if(s->zstream.avail_in == 0){
+            err = read_block(s);
+        }
+        //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
+        zerr = inflate(&s->zstream, Z_NO_FLUSH);
+        //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
+        if(zerr == Z_STREAM_END) break;
+        //dprintf("> zerr=%d\n", zerr);
+        err = zerror(s, zerr);
+        if(err) goto exit;
+    }
+    err = n - s->zstream.avail_out;
+    s->plain_bytes += err;
+    if(size != 1) err /= size;
+  exit:
+    set_error(s, err);
+    //dprintf("< err=%d\n", err);
+    return err;
+}
+
+/** Print to the underlying stream.
+ * Returns 0 if the formatted output is too big for the internal buffer.
+ *
+ * @param io lzi stream
+ * @param msg format to use
+ * @param args arguments
+ * @return result of the print
+ */
+static int lzi_print(IOStream *io, const char *msg, va_list args){
+    char buf[1024];
+    int buf_n = sizeof(buf);
+    int n;
+    LZIState *s = lzi_state(io);
+    if(!LZIState_writeable(s)){
+        n = -EINVAL;
+        goto exit;
+    }
+    n = vsnprintf(buf, buf_n, (char*)msg, args);
+    if(n < 0) goto exit;
+    if(n > buf_n){
+        n = 0;
+    } else {
+        n = lzi_write(io, buf, 1, n);
+    }
+  exit:
+    return n;
+}
+
+/** Read a character from the underlying stream
+ *
+ * @param io lzi stream
+ * @return character read, IOSTREAM_EOF on end of file (or error)
+ */
+static int lzi_getc(IOStream *io){
+    int err;
+    char c;
+    err = lzi_read(io, &c, 1, 1);
+    if(err < 1) c = EOF;
+    err = (c==EOF ? IOSTREAM_EOF : c);
+    return err;
+}
+
+static int flush_output(LZIState *s, int mode){
+    int err = 0, zerr;
+    int done = 0;
+    int avail_out_old;
+    int count = 10;
+
+    //dprintf("> avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
+    if(s->flushed == 1 + mode) goto exit;
+    //s->zstream.avail_in = 0; /* should be zero already anyway */
+    for(;;){
+        // Write any available output.
+        if(done || s->zstream.avail_out == 0){
+            err = write_block(s);
+            if(err) goto exit;
+            if(done) break;
+        }
+        //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
+        avail_out_old = s->zstream.avail_out;
+        zerr = deflate(&s->zstream, mode);
+        err = zerror(s, zerr);
+        //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
+        //dprintf("> deflate=%d\n", err);
+        //done = (s->zstream.avail_out != 0);
+        //done = (s->zstream.avail_in == 0) && (s->zstream.avail_out == avail_out_old);
+        if(0 && mode == Z_FINISH){
+            done = (zerr ==  Z_STREAM_END);
+        } else {
+            done = (s->zstream.avail_in == 0)
+                //&& (s->zstream.avail_out == avail_out_old)
+                && (s->zstream.avail_out != 0);
+        }
+    }
+    s->flushed = 1 + mode;
+  exit:
+    //dprintf("< err=%d\n", err);
+    return err;
+}
+
+/** Flush any pending input to the underlying stream.
+ *
+ * @param s lzi stream
+ * @return 0 on success, error code otherwise
+ */
+static int lzi_flush(IOStream *io){
+    int err = 0;
+    LZIState *s = lzi_state(io);
+    //dprintf(">\n");
+    if(!LZIState_writeable(s)){
+        err = -EINVAL;
+        goto exit;
+    }
+    err = flush_output(s, Z_SYNC_FLUSH);
+    if(err) goto exit;
+    err = IOStream_flush(s->io);
+  exit:
+    set_error(s, err);
+    //dprintf("< err=%d\n", err);
+    return (err < 0 ? err : 0);
+}
+
+/** Check if a stream has an error.
+ *
+ * @param s lzi stream
+ * @return code if has an error, 0 otherwise
+ */
+static int lzi_error(IOStream *s){
+    int err = 0;
+    LZIState *state = lzi_state(s);
+    err = state->error;
+    if(err) goto exit;
+    err = IOStream_error(state->io);
+  exit:
+    return err;
+}
+
+/** Close an lzi stream.
+ *
+ * @param s lzi stream to close
+ * @return result of the close
+ */
+static int lzi_close(IOStream *io){
+    int err = 0;
+    LZIState *s = lzi_state(io);
+    if(LZIState_writeable(s)){
+        err = flush_output(s, Z_FINISH);
+        if(err) goto exit;
+        err = write_terminator(s);
+        if(err) goto exit;
+        err = IOStream_flush(s->io);
+    }   
+  exit:
+    err = IOStream_close(s->io);
+    set_error(s, err);
+    return err;
+}
+
+/** Free an lzi stream.
+ *
+ * @param s lzi stream
+ */
+static void lzi_free(IOStream *s){
+    LZIState *state = lzi_state(s);
+    IOStream_free(state->io);
+    LZIState_free(state);
+    s->data = NULL;
+}
+
+/** Create an lzi stream for an IOStream.
+ *
+ * @param io stream to wrap
+ * @return new IOStream using f for i/o
+ */
+IOStream *lzi_stream_new(IOStream *io, const char *mode){
+    int err = -ENOMEM;
+    int flags = 0;
+    IOStream *zio = NULL;
+    LZIState *state = NULL;
+
+    zio = ALLOCATE(IOStream);
+    if(!zio) goto exit;
+    err = mode_flags(mode, &flags);
+    if(err) goto exit;
+    state = LZIState_new(io, flags);
+    if(!state) goto exit;
+    err = 0;
+    zio->data = state;
+    zio->methods = &lzi_methods;
+  exit:
+    if(err){
+        if(state) LZIState_free(state);
+        if(zio) deallocate(zio);
+        zio = NULL;
+    }
+    return zio;
+}
+
+/** IOStream version of fdopen().
+ *
+ * @param fd file descriptor
+ * @param flags giving the mode to open in (as for fdopen())
+ * @return new stream for the open file, or NULL if failed
+ */
+IOStream *lzi_stream_fdopen(int fd, const char *mode){
+    int err = -ENOMEM;
+    IOStream *io = NULL, *zio = NULL;
+    io = file_stream_fdopen(fd, mode);
+    if(!io) goto exit;
+    zio = lzi_stream_new(io, mode);
+    if(!io) goto exit;
+    err = 0;
+  exit:
+    if(err){
+        IOStream_free(io);
+        IOStream_free(zio);
+        zio = NULL;
+    }
+    return zio;
+}
+#endif
diff --git a/tools/libxutil/lzi_stream.h b/tools/libxutil/lzi_stream.h
new file mode 100644 (file)
index 0000000..0ad4f8d
--- /dev/null
@@ -0,0 +1,36 @@
+#/* $Id: lzi_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */
+/*
+ * Copyright (C) 2003 Hewlett-Packard Company.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _SP_LZI_STREAM_H_
+#define _SP_LZI_STREAM_H_
+
+#ifndef __KERNEL__
+#include "iostream.h"
+
+extern IOStream *lzi_stream_new(IOStream *io, const char *mode);
+extern IOStream *lzi_stream_fopen(const char *file, const char *mode);
+extern IOStream *lzi_stream_fdopen(int fd, const char *mode);
+extern IOStream *lzi_stream_io(IOStream *zio);
+
+extern int lzi_stream_plain_bytes(IOStream *io);
+extern int lzi_stream_comp_bytes(IOStream *io);
+extern float lzi_stream_ratio(IOStream *io);
+
+#endif
+#endif /* !_SP_FILE_STREAM_H_ */
diff --git a/tools/libxutil/lzo_stream.c b/tools/libxutil/lzo_stream.c
new file mode 100644 (file)
index 0000000..bf7c348
--- /dev/null
@@ -0,0 +1,596 @@
+/* $Id: lzo_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */
+#define __FILE_ID_INFO "$Id: lzo_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $"
+#include <what.h>
+static char __rcsid[] __attribute__((unused)) = WHAT_ID __FILE_ID_INFO;
+/*
+ * Copyright (C) 2003 Hewlett-Packard Company.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/** @file
+ * An IOStream implementation using LZO to provide compression and decompression.
+ * This is designed to provide reasonable compression without output latency.
+ * Flushing an LZO stream flushes all pending data to the underlying stream.
+ * This is essential for stream-based (e.g. networked) applications.
+ *
+ * A compressed data stream is a sequence of blocks.
+ * Each block except the last is the plain data size followed by the compressed data size
+ * and the compressed data. The last block has plain data size zero and omits the rest.
+ * Sizes are 4-byte unsigned in network order. If the compressed size is smaller than
+ * the plain size the block data is compressed, otherwise it is plain (uncompressed).
+ *
+ * This format allows compressed data to be read from a stream without reading
+ * past the logical end of compressed data.
+ *
+ * @author Mike Wray <mike.wray@hpl.hp.com>
+ */
+#ifndef __KERNEL__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "lzo1x.h"
+
+#include "allocate.h"
+#include "lzo_stream.h"
+#include "file_stream.h"
+#include "marshal.h"
+
+#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] LZO>%s" fmt, __FUNCTION__, ##args)
+#define wprintf(fmt, args...) fprintf(stderr, "[WARN]  LZO>%s" fmt, __FUNCTION__, ##args)
+#define iprintf(fmt, args...) fprintf(stdout, "[INFO]  LZO>%s" fmt, __FUNCTION__, ##args)
+#define eprintf(fmt, args...) fprintf(stderr, "[ERROR] LZO>%s" fmt, __FUNCTION__, ##args)
+
+static int lzo_read(IOStream *s, void *buf, size_t size, size_t count);
+static int lzo_write(IOStream *s, const void *buf, size_t size, size_t count);
+static int lzo_print(IOStream *s, const char *msg, va_list args);
+static int lzo_getc(IOStream *s);
+static int lzo_error(IOStream *s);
+static int lzo_close(IOStream *s);
+static void lzo_free(IOStream *s);
+static int lzo_flush(IOStream *s);
+
+enum {
+    LZO_WRITE = 1,
+    LZO_READ = 2,
+};
+
+/** Methods used by a gzFile* IOStream. */
+static const IOMethods lzo_methods = {
+    read: lzo_read,
+    write: lzo_write,
+    print: lzo_print,
+    getc:  lzo_getc,
+    error: lzo_error,
+    close: lzo_close,
+    free:  lzo_free,
+    flush: lzo_flush,
+};
+
+//#define PLAIN_SIZE (64 * 1024)
+//#define PLAIN_SIZE (128 * 1024)
+#define PLAIN_SIZE (512 * 1024)
+
+//#define NOCOMPRESS
+
+typedef struct LZOState {
+    /** Flags. */
+    int flags;
+    /** Error indicator. */
+    int error;
+    /** Underlying stream for I/O. */
+    IOStream *io;
+    /** Working memory (only needed for compression, not decompression). */
+    lzo_byte *memory;
+    /** Buffer for plain (uncompressed) data. */
+    lzo_byte *plain;
+    /** Size of the plain buffer. */
+    lzo_uint plain_size;
+    /** Pointer into the plain buffer. */
+    lzo_byte *plain_ptr;
+    /** Number of bytes of plain data available. */
+    lzo_uint plain_n;
+    /** Buffer for compressed data. */
+    lzo_byte *comp;
+    /** Size of the compressed buffer. */
+    lzo_uint comp_size;
+
+    int plain_bytes;
+    int comp_bytes;
+} LZOState;
+
+void LZOState_free(LZOState *z){
+    if(!z) return;
+    deallocate(z->memory);
+    deallocate(z->plain);
+    deallocate(z->comp);
+    deallocate(z);
+}
+
+/** Maximum size of compressed data for the given plain data size.
+ *
+ * @param plain_size size of plain data
+ * @return maximum size of compressed data
+ */
+static int comp_size(int plain_size){
+    return plain_size + (plain_size / 64) + 16 + 3;
+}
+
+static int mode_flags(const char *mode, int *flags){
+    int err = 0;
+    int r=0, w=0;
+    if(!mode){
+        err = -EINVAL;
+        goto exit;
+    }
+    for(; *mode; mode++){
+        if(*mode == 'w') w = 1;
+        if(*mode == 'r') r = 1;
+    }
+    if(r + w != 1){
+        err = -EINVAL;
+        goto exit;
+    }
+    if(r) *flags |= LZO_READ;
+    if(w) *flags |= LZO_WRITE;
+  exit:
+    return err;
+}
+
+/** Get the stream state.
+ * 
+ * @param s lzo stream
+ * @return stream state.
+ */
+static inline LZOState * lzo_state(IOStream *s){
+    return s->data;
+}
+
+IOStream *lzo_stream_io(IOStream *s){
+    LZOState *state = lzo_state(s);
+    return state->io;
+}
+
+static inline void set_error(LZOState *state, int err){
+    if(err < 0 && !state->error){
+        state->error = err;
+    }
+}
+
+int lzo_stream_plain_bytes(IOStream *s){
+    LZOState *state = lzo_state(s);
+    return state->plain_bytes;
+}
+
+int lzo_stream_comp_bytes(IOStream *s){
+    LZOState *state = lzo_state(s);
+    return state->comp_bytes;
+}
+
+float lzo_stream_ratio(IOStream *s){
+    LZOState *state = lzo_state(s);
+    float ratio = 0.0;
+    if(state->comp_bytes){
+        ratio = ((float) state->comp_bytes)/((float) state->plain_bytes);
+    }
+    return ratio;
+}
+
+static inline int LZOState_writeable(LZOState *state){
+    return (state->flags & LZO_WRITE) != 0;
+}
+
+static inline int LZOState_readable(LZOState *state){
+    return (state->flags & LZO_READ) != 0;
+}
+
+LZOState * LZOState_new(IOStream *io, int flags){
+    int err = -ENOMEM;
+    LZOState *z = ALLOCATE(LZOState);
+    //dprintf(">\n");
+    if(!z) goto exit;
+    z->io = io;
+    z->flags = flags;
+    if(LZOState_writeable(z)){
+        z->memory = allocate(LZO1X_1_MEM_COMPRESS);
+        if(!z->memory) goto exit;
+    }
+    z->plain_size = PLAIN_SIZE;
+    z->plain = allocate(z->plain_size);
+    if(!z->plain) goto exit;
+    z->plain_ptr = z->plain;
+    z->comp_size = comp_size(z->plain_size);
+    z->comp = allocate(z->comp_size);
+    if(!z->comp) goto exit;
+    err = 0;
+  exit:
+    if(err){
+        LZOState_free(z);
+        z = NULL;
+    }
+    //dprintf("< z=%p\n", z);
+    return z;
+}
+
+static int lzo_compress(LZOState *state){
+    int err = 0;
+    int k, comp_n;
+    //dprintf(">\n");
+    //dprintf(">plain=%p plain_n=%d comp=%p memory=%p\n", state->plain, state->plain_n, state->comp, state->memory);
+    // Compress the plain buffer.
+    err = lzo1x_1_compress(state->plain, state->plain_n,
+                           state->comp, &comp_n,
+                           state->memory);
+    //dprintf("> err=%d plain_n=%d comp_n=%d\n", err, state->plain_n, comp_n);
+    // Write plain size, compressed size.
+    err = marshal_uint32(state->io, state->plain_n);
+    if(err) goto exit;
+    err = marshal_uint32(state->io, comp_n);
+    if(err) goto exit;
+    //dprintf("> write data...\n");
+    // Write the smaller of the compressed and plain data.
+    if(state->plain_n < comp_n){
+        k = state->plain_n;
+        err = marshal_bytes(state->io, state->plain, state->plain_n);
+    } else {
+        k = comp_n;
+        err = marshal_bytes(state->io, state->comp, comp_n);
+    }
+    if(err) goto exit;
+    // Total output bytes.
+    k+= 8;
+    //dprintf("> wrote %d bytes\n", k);
+    state->plain_bytes += state->plain_n;
+    state->comp_bytes += k;
+    //dprintf("> plain=%d, comp=%d, ratio=%3.2f\n",
+    //        state->plain_bytes, state->comp_bytes,
+    //        ((float)state->comp_bytes)/((float)state->plain_bytes));
+    // Reset the plain buffer.
+    state->plain_ptr = state->plain;
+    state->plain_n = 0;
+    err = k;
+  exit:
+    //dprintf("< err=%d\n", err);
+    return err;
+}
+
+static int lzo_decompress(LZOState *state){
+    int plain_n, comp_n;
+    int err, k;
+    //dprintf(">\n");
+    err = unmarshal_uint32(state->io, &plain_n);
+    //dprintf("> err=%d plain_n=%d\n", err, plain_n);
+    if(err) goto exit;
+    state->comp_bytes += 4;
+    if(plain_n == 0) goto exit;
+    err = unmarshal_uint32(state->io, &comp_n);
+    //dprintf("> err=%d comp_n=%d\n", err, comp_n);
+    if(err) goto exit;
+    state->comp_bytes += 4;
+    if(plain_n > state->plain_size){
+        err = -EINVAL;
+        goto exit;
+    }
+    if(comp_n > plain_n){
+        //dprintf("> reading plain data %d...\n", plain_n);
+        k = plain_n;
+        err = unmarshal_bytes(state->io, state->plain, plain_n);
+        state->plain_n = plain_n;
+    } else {
+        //dprintf("> reading comp data %d...\n", comp_n);
+        k = comp_n;
+        err = unmarshal_bytes(state->io, state->comp, comp_n);
+        //dprintf("> decompress comp_n=%d\n", comp_n);
+        err = lzo1x_decompress(state->comp, comp_n,
+                               state->plain, &state->plain_n,
+                               state->memory);
+        //dprintf("> err=%d plain=%d state->plain_n=%d\n", err, plain_n, state->plain_n);
+        if(err != LZO_E_OK || state->plain_n != plain_n){
+            // Bad. Corrupted input.
+            err = -EINVAL;
+            eprintf("> Corrupted!\n");
+            goto exit;
+        }
+    }
+    state->comp_bytes += k;
+    state->plain_bytes += state->plain_n;
+    state->plain_ptr = state->plain;
+    err = k;
+  exit:
+    //dprintf("< err=%d\n", err);
+    return err;
+}
+
+/** Write to the underlying stream using fwrite();
+ *
+ * @param stream destination
+ * @param buf data
+ * @param size size of data elements
+ * @param count number of data elements to write
+ * @return number of data elements written
+ */
+static int lzo_write(IOStream *s, const void *buf, size_t size, size_t count){
+    int err = 0;
+    int n = size * count; // Total number of bytes to write.
+    int chunk;            // Size of chunk to write.
+    int remaining;        // Number of bytes remaining to write.
+    int space;            // Amount of space left in plain buffer.
+    LZOState *state = lzo_state(s);
+#ifdef NOCOMPRESS
+    //dprintf("> buf=%p size=%d count=%d\n", buf, size, count);
+    err = IOStream_write(state->io, buf, size, count);
+    //dprintf("< err=%d\n", err);
+#else
+    //dprintf("> buf=%p size=%d count=%d n=%d\n", buf, size, count, n);
+    remaining = n;
+    space = state->plain_size - state->plain_n;
+    //dprintf("> plain=%p plain_ptr=%p plain_n=%d space=%d\n",
+    //        state->plain, state->plain_ptr, state->plain_n, space);
+    while(remaining){
+        chunk = remaining;
+        if(chunk > space) chunk = space;
+        //dprintf("> memcpy %p %p %d\n", state->plain_ptr, buf, chunk);
+        memcpy(state->plain_ptr, buf, chunk);
+        remaining -= chunk;
+        space -= chunk;
+        state->plain_ptr += chunk;
+        state->plain_n += chunk;
+        if(space == 0){
+            // Input buffer is full. Compress and write it.
+            err = lzo_compress(state);
+            if(err < 0) goto exit;
+            space = state->plain_size - state->plain_n;
+        }
+    }
+    err = (size > 1 ? n / size : n);
+  exit:
+    set_error(state, err);
+#endif
+    return err;
+}
+
+
+/** Read from the underlying stream.
+ *
+ * @param stream input
+ * @param buf where to put input
+ * @param size size of data elements
+ * @param count number of data elements to read
+ * @return number of data elements read
+ */
+static int lzo_read(IOStream *s, void *buf, size_t size, size_t count){
+    int err = 0;
+    int k = 0;                     // Number of (plain) bytes read.
+    int remaining = size * count;  // Number of bytes remaining to read.
+    int chunk;                     // Size of chunk to read.
+    LZOState *state = lzo_state(s);
+#ifdef NOCOMPRESS
+    //dprintf("> buf=%p size=%d count=%d\n", buf, size, count);
+    err = IOStream_read(state->io, buf, size, count);
+    //dprintf("< err=%d\n", err);
+#else
+    if(!(state->flags & LZO_READ)){
+        err = -EINVAL;
+        goto exit;
+    }
+    while(remaining){
+        if(state->plain_n == 0){
+            // No more plain input, decompress some more.
+            err = lzo_decompress(state);
+            if(err < 0) goto exit;
+            // Stop reading if there is no more input.
+            if(err == 0 || state->plain_n == 0) break;
+        }
+        chunk = remaining;
+        if(chunk > state->plain_n) chunk = state->plain_n;
+        memcpy(buf, state->plain_ptr, chunk);
+        k += chunk;
+        buf += chunk;
+        state->plain_ptr += chunk;
+        state->plain_n -= chunk;
+        remaining -= chunk;
+    }
+    err = k;
+  exit:
+    set_error(state, err);
+#endif
+    return err;
+}
+
+/** Print to the underlying stream.
+ * Returns 0 if the formatted output is too big for the internal buffer.
+ *
+ * @param s lzo stream
+ * @param msg format to use
+ * @param args arguments
+ * @return result of the print
+ */
+static int lzo_print(IOStream *s, const char *msg, va_list args){
+    char buf[1024];
+    int buf_n = sizeof(buf);
+    int n;
+    LZOState *state = lzo_state(s);
+    if(!LZOState_writeable(state)){
+        n = -EINVAL;
+        goto exit;
+    }
+    n = vsnprintf(buf, buf_n, (char*)msg, args);
+    if(n < 0) goto exit;
+    if(n > buf_n){
+        n = 0;
+    } else {
+        n = lzo_write(s, buf, 1, n);
+    }
+  exit:
+    return n;
+}
+
+/** Read a character from the underlying stream
+ *
+ * @param s lzo stream
+ * @return character read, IOSTREAM_EOF on end of file (or error)
+ */
+static int lzo_getc(IOStream *s){
+    int err;
+    char c;
+    err = lzo_read(s, &c, 1, 1);
+    if(err < 1) c = EOF;
+    err = (c==EOF ? IOSTREAM_EOF : c);
+    return err;
+}
+
+/** Flush any pending input to the underlying stream.
+ *
+ * @param s lzo stream
+ * @return 0 on success, error code otherwise
+ */
+static int lzo_flush(IOStream *s){
+    int err = 0;
+    LZOState *state = lzo_state(s);
+    //dprintf(">\n");
+#ifdef NOCOMPRESS
+    err = IOStream_flush(state->io);
+#else    
+    if(!LZOState_writeable(state)){
+        err = -EINVAL;
+        goto exit;
+    }
+    if(state->plain_n){
+        err = lzo_compress(state);
+        if(err < 0) goto exit;
+    }
+    err = IOStream_flush(state->io);
+  exit:
+    set_error(state, err);
+#endif
+    //dprintf("< err=%d\n", err);
+    return (err < 0 ? err : 0);
+}
+
+/** Check if a stream has an error.
+ *
+ * @param s lzo stream
+ * @return code if has an error, 0 otherwise
+ */
+static int lzo_error(IOStream *s){
+    int err = 0;
+    LZOState *state = lzo_state(s);
+    err = state->error;
+    if(err) goto exit;
+    err = IOStream_error(state->io);
+  exit:
+    return err;
+}
+
+int lzo_stream_finish(IOStream *s){
+    int err = 0;
+    LZOState *state = lzo_state(s);
+    if(!LZOState_writeable(state)){
+        err = -EINVAL;
+        goto exit;
+    }
+    err = lzo_flush(s);
+    if(err < 0) goto exit;
+    err = marshal_int32(state->io, 0);
+  exit:
+    return err;
+}        
+
+/** Close an lzo stream.
+ *
+ * @param s lzo stream to close
+ * @return result of the close
+ */
+static int lzo_close(IOStream *s){
+    int err = 0;
+    LZOState *state = lzo_state(s);
+#ifdef NOCOMPRESS
+    err = IOStream_close(state->io);
+#else    
+    if(LZOState_writeable(state)){
+        err = lzo_stream_finish(s);
+    }        
+    err = IOStream_close(state->io);
+    set_error(state, err);
+#endif
+    return err;
+}
+
+/** Free an lzo stream.
+ *
+ * @param s lzo stream
+ */
+static void lzo_free(IOStream *s){
+    LZOState *state = lzo_state(s);
+    IOStream_free(state->io);
+    LZOState_free(state);
+    s->data = NULL;
+}
+
+/** Create an lzo stream for an IOStream.
+ *
+ * @param io stream to wrap
+ * @return new IOStream using f for i/o
+ */
+IOStream *lzo_stream_new(IOStream *io, const char *mode){
+    int err = -ENOMEM;
+    int flags = 0;
+    IOStream *zio = NULL;
+    LZOState *state = NULL;
+
+    zio = ALLOCATE(IOStream);
+    if(!zio) goto exit;
+    err = mode_flags(mode, &flags);
+    if(err) goto exit;
+    state = LZOState_new(io, flags);
+    if(!state) goto exit;
+    err = 0;
+    zio->data = state;
+    zio->methods = &lzo_methods;
+  exit:
+    if(err){
+        if(state) LZOState_free(state);
+        if(zio) deallocate(zio);
+        zio = NULL;
+    }
+    return zio;
+}
+
+/** IOStream version of fdopen().
+ *
+ * @param fd file descriptor
+ * @param flags giving the mode to open in (as for fdopen())
+ * @return new stream for the open file, or NULL if failed
+ */
+IOStream *lzo_stream_fdopen(int fd, const char *mode){
+    int err = -ENOMEM;
+    IOStream *io = NULL, *zio = NULL;
+    io = file_stream_fdopen(fd, mode);
+    if(!io) goto exit;
+    zio = lzo_stream_new(io, mode);
+    if(!io) goto exit;
+    err = 0;
+  exit:
+    if(err){
+        IOStream_free(io);
+        IOStream_free(zio);
+        zio = NULL;
+    }
+    return zio;
+}
+#endif
diff --git a/tools/libxutil/lzo_stream.h b/tools/libxutil/lzo_stream.h
new file mode 100644 (file)
index 0000000..493da7b
--- /dev/null
@@ -0,0 +1,36 @@
+#/* $Id: lzo_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */
+/*
+ * Copyright (C) 2003 Hewlett-Packard Company.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _SP_LZO_STREAM_H_
+#define _SP_LZO_STREAM_H_
+
+#ifndef __KERNEL__
+#include "iostream.h"
+
+extern IOStream *lzo_stream_new(IOStream *io, const char *mode);
+extern IOStream *lzo_stream_fopen(const char *file, const char *mode);
+extern IOStream *lzo_stream_fdopen(int fd, const char *mode);
+extern IOStream *lzo_stream_io(IOStream *zio);
+
+extern int lzo_stream_plain_bytes(IOStream *io);
+extern int lzo_stream_comp_bytes(IOStream *io);
+extern float lzo_stream_ratio(IOStream *io);
+
+#endif
+#endif /* !_SP_FILE_STREAM_H_ */
diff --git a/tools/libxutil/marshal.c b/tools/libxutil/marshal.c
new file mode 100644 (file)
index 0000000..21691d4
--- /dev/null
@@ -0,0 +1,207 @@
+#include <errno.h>
+#include "sys_net.h"
+#include "allocate.h"
+#include "marshal.h"
+
+#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
+#define wprintf(fmt, args...) IOStream_print(iostderr, "[WARN]  %s" fmt, __FUNCTION__, ##args)
+#define iprintf(fmt, args...) IOStream_print(iostdout, "[INFO]  %s" fmt, __FUNCTION__, ##args)
+#define eprintf(fmt, args...) IOStream_print(iostderr, "[ERROR] %s" fmt, __FUNCTION__, ##args)
+
+
+#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof((ary)[0]))
+
+/* Messages are coded as msgid followed by message fields.
+ * Initial message on any channel is hello - so can check version
+ * compatibility.
+ *
+ * char* -> uint16_t:n <n bytes>
+ * ints/uints go as suitable number of bytes (e.g. uint16_t is 2 bytes).
+ * optional fields go as '1' <val> or '0' (the 0/1 is 1 byte).
+ * lists go as ('1' <elt>)* '0'
+ */
+
+int marshal_flush(IOStream *io){
+    int err  = 0;
+    err = IOStream_flush(io);
+    return err;
+}
+
+int marshal_bytes(IOStream *io, void *s, uint32_t s_n){
+    int err = 0;
+    int n;
+    n = IOStream_write(io, s, s_n);
+    if(n < 0){
+        err = n;
+    } else if (n < s_n){
+        wprintf("> Wanted %d, got %d\n", s_n, n);
+        err = -EIO;
+    }
+    return err;
+}
+
+int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n){
+    int err = 0;
+    int n;
+    //dprintf("> s_n=%d\n", s_n);
+    n = IOStream_read(io, s, s_n);
+    //dprintf("> n=%d\n", n);
+    if(n < 0){
+        err = n;
+    } else if(n < s_n){
+        wprintf("> Wanted %d, got %d\n", s_n, n);
+        err = -EIO;
+    }
+    //dprintf("< err=%d\n", err);
+    return err;
+}
+
+int marshal_uint8(IOStream *io, uint8_t x){
+    return marshal_bytes(io, &x, sizeof(x));
+}
+
+int unmarshal_uint8(IOStream *io, uint8_t *x){
+    return unmarshal_bytes(io, x, sizeof(*x));
+}
+
+int marshal_uint16(IOStream *io, uint16_t x){
+    x = htons(x);
+    return marshal_bytes(io, &x, sizeof(x));
+}
+
+int unmarshal_uint16(IOStream *io, uint16_t *x){
+    int err = 0;
+    err = unmarshal_bytes(io, x, sizeof(*x));
+    *x = ntohs(*x);
+    return err;
+}
+
+int marshal_int32(IOStream *io, int32_t x){
+    int err = 0;
+    //dprintf("> x=%d\n", x);
+    x = htonl(x);
+    err = marshal_bytes(io, &x, sizeof(x));
+    //dprintf("< err=%d\n", err);
+    return err;
+}
+
+int unmarshal_int32(IOStream *io, int32_t *x){
+    int err = 0;
+    //dprintf(">\n");
+    err = unmarshal_bytes(io, x, sizeof(*x));
+    *x = ntohl(*x);
+    //dprintf("< err=%d x=%d\n", err, *x);
+    return err;
+}
+
+int marshal_uint32(IOStream *io, uint32_t x){
+    int err = 0;
+    //dprintf("> x=%u\n", x);
+    x = htonl(x);
+    err = marshal_bytes(io, &x, sizeof(x));
+    //dprintf("< err=%d\n", err);
+    return err;
+}
+
+int unmarshal_uint32(IOStream *io, uint32_t *x){
+    int err = 0;
+    //dprintf(">\n");
+    err = unmarshal_bytes(io, x, sizeof(*x));
+    *x = ntohl(*x);
+    //dprintf("< err=%d x=%u\n", err, *x);
+    return err;
+}
+
+int marshal_uint64(IOStream *io, uint64_t x){
+    int err;
+    err = marshal_uint32(io, (uint32_t) ((x >> 32) & 0xffffffff));
+    if(err) goto exit;
+    err = marshal_uint32(io, (uint32_t) ( x        & 0xffffffff));
+  exit:
+    return err;
+}
+
+int unmarshal_uint64(IOStream *io, uint64_t *x){
+    int err = 0;
+    uint32_t hi, lo;
+    err = unmarshal_uint32(io, &hi);
+    if(err) goto exit;
+    err = unmarshal_uint32(io, &lo);
+    *x = (((uint64_t) hi) << 32) | lo;
+  exit:
+    return err;
+}
+
+int marshal_net16(IOStream *io, net16_t x){
+    return marshal_bytes(io, &x, sizeof(x));
+}
+
+int unmarshal_net16(IOStream *io, net16_t *x){
+    int err = 0;
+    err = unmarshal_bytes(io, x, sizeof(*x));
+    return err;
+}
+
+int marshal_net32(IOStream *io, net32_t x){
+    return marshal_bytes(io, &x, sizeof(x));
+}
+
+int unmarshal_net32(IOStream *io, net32_t *x){
+    int err = 0;
+    err = unmarshal_bytes(io, x, sizeof(*x));
+    return err;
+}
+
+int marshal_string(IOStream *io, char *s, uint32_t s_n){
+    int err;
+    //dprintf("> s=%s\n", s);
+    err = marshal_uint32(io, s_n);
+    if(err) goto exit;
+    err = marshal_bytes(io, s, s_n);
+  exit:
+    //dprintf("< err=%d\n", err);
+    return err;
+}
+
+int unmarshal_string(IOStream *io, char *s, uint32_t s_n){
+    int err = 0, val_n = 0;
+    //dprintf(">\n");
+    err = unmarshal_uint32(io, &val_n);
+    if(err) goto exit;
+    if(val_n >= s_n){
+        err = -EINVAL;
+        goto exit;
+    }
+    err = unmarshal_bytes(io, s, val_n);
+    if(err) goto exit;
+    s[val_n] = '\0';
+  exit:
+    //dprintf("< err=%d s=%s\n", err, s);
+    return err;
+}
+
+int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n){
+    int err = 0, val_n = 0;
+    char *val = NULL;
+    //dprintf(">\n");
+    err = unmarshal_uint32(io, &val_n);
+    if(err) goto exit;
+    val = allocate(val_n + 1);
+    if(!val){
+        err = -ENOMEM;
+        goto exit;
+    }
+    err = unmarshal_bytes(io, val, val_n);
+    if(err) goto exit;
+    val[val_n] = '\0';
+  exit:
+    if(err){
+        if(val) deallocate(val);
+        val = NULL;
+        val_n = 0;
+    }
+    *s = val;
+    if(s_n) *s_n = val_n;
+    //dprintf("< err=%d s=%s\n", err, *s);
+    return err;
+}
diff --git a/tools/libxutil/marshal.h b/tools/libxutil/marshal.h
new file mode 100644 (file)
index 0000000..9a9d465
--- /dev/null
@@ -0,0 +1,43 @@
+/* $Id: marshal.h,v 1.1 2003/10/17 15:48:43 mjw Exp $ */
+#ifndef _SP_MARSHAL_H_
+#define _SP_MARSHAL_H_
+
+#include "iostream.h"
+
+/** A 16-bit uint in network order, e.g. a port number. */
+typedef uint16_t net16_t;
+
+/** A 32-bit uint in network order, e.g. an IP address. */
+typedef uint32_t net32_t;
+
+extern int marshal_flush(IOStream *io);
+
+extern int marshal_bytes(IOStream *io, void *s, uint32_t s_n);
+extern int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n);
+
+extern int marshal_uint8(IOStream *io, uint8_t x);
+extern int unmarshal_uint8(IOStream *io, uint8_t *x);
+
+extern int marshal_uint16(IOStream *io, uint16_t x);
+extern int unmarshal_uint16(IOStream *io, uint16_t *x);
+
+extern int marshal_uint32(IOStream *io, uint32_t x);
+extern int unmarshal_uint32(IOStream *io, uint32_t *x);
+
+extern int marshal_int32(IOStream *io, int32_t x);
+extern int unmarshal_int32(IOStream *io, int32_t *x);
+
+extern int marshal_uint64(IOStream *io, uint64_t x);
+extern int unmarshal_uint64(IOStream *io, uint64_t *x);
+
+extern int marshal_net16(IOStream *io, net16_t x);
+extern int unmarshal_net16(IOStream *io, net16_t *x);
+
+extern int marshal_net32(IOStream *io, net32_t x);
+extern int unmarshal_net32(IOStream *io, net32_t *x);
+
+extern int marshal_string(IOStream *io, char *s, uint32_t s_n);
+extern int unmarshal_string(IOStream *io, char *s, uint32_t s_n);
+extern int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n);
+
+#endif /* ! _SP_MARSHAL_H_ */
diff --git a/tools/libxutil/socket_stream.c b/tools/libxutil/socket_stream.c
new file mode 100644 (file)
index 0000000..cfa6e3a
--- /dev/null
@@ -0,0 +1,259 @@
+/* $Id: socket_stream.c,v 1.9 2004/03/05 14:45:34 mjw Exp $ */
+/*
+ * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/** @file
+ * An IOStream implementation using sockets.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include "allocate.h"
+#include "socket_stream.h"
+
+#define MODULE_NAME "sock"
+#define DEBUG 0
+//#undef DEBUG
+#include "debug.h"
+
+static int socket_read(IOStream *s, void *buf, size_t n);
+static int socket_write(IOStream *s, const void *buf, size_t n);
+static int socket_error(IOStream *s);
+static int socket_close(IOStream *s);
+static void socket_free(IOStream *s);
+static int socket_flush(IOStream *s);
+
+/** Methods used by a socket IOStream. */
+static const IOMethods socket_methods = {
+    read:  socket_read,
+    write: socket_write,
+    error: socket_error,
+    close: socket_close,
+    free:  socket_free,
+    flush: socket_flush,
+};
+
+/** Get the socket data.
+ * 
+ * @param io socket stream
+ * @return data
+ */
+static inline SocketData * socket_data(IOStream *io){
+    return (SocketData *)io->data;
+}
+
+/** Test if a stream is a socket stream.
+ *
+ * @param io stream
+ * @return 0 if a socket stream, -EINVAL if not
+ */
+int socket_stream_check(IOStream *io){
+    return (io && io->methods == &socket_methods ? 0 : -EINVAL);
+}
+
+/** Get the data for a socket stream.
+ *
+ * @param io stream
+ * @param data return value for the data
+ * @return 0 if a socket stream, -EINVAL if not
+ */
+int socket_stream_data(IOStream *io, SocketData **data){
+    int err = socket_stream_check(io);
+    if(err){
+        *data = NULL;
+    } else {
+        *data = socket_data(io);
+    }
+    return err;
+}
+
+/** Set the destination address for a socket stream.
+ *
+ * @param io stream
+ * @param addr address
+ * @return 0 if a socket stream, -EINVAL if not
+ */
+int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr){
+    int err = 0;
+    SocketData *data = NULL;
+    err = socket_stream_data(io, &data);
+    if(!err){
+        data->daddr = *addr;
+    }
+    return err;
+}
+
+/** Set the send flags for a socket stream.
+ *
+ * @param io stream
+ * @param flags flags
+ * @return 0 if a socket stream, -EINVAL if not
+ */
+int socket_stream_set_flags(IOStream *io, int flags){
+    int err = 0;
+    SocketData *data = NULL;
+    err = socket_stream_data(io, &data);
+    if(!err){
+        data->flags = flags;
+    }
+    return err;
+}
+
+/** Write to the underlying socket using sendto.
+ *
+ * @param stream input
+ * @param buf where to put input
+ * @param n number of bytes to write
+ * @return number of bytes written
+ */
+static int socket_write(IOStream *s, const void *buf, size_t n){
+    SocketData *data = socket_data(s);
+    struct sockaddr *daddr = (struct sockaddr *)&data->daddr;
+    socklen_t daddr_n = sizeof(data->daddr);
+    int k;
+    dprintf("> sock=%d addr=%s:%d n=%d\n",
+            data->fd, inet_ntoa(data->daddr.sin_addr), ntohs(data->daddr.sin_port), n);
+    if(0){
+        struct sockaddr_in self = {};
+        socklen_t self_n;
+        getsockname(data->fd, (struct sockaddr *)&self, &self_n);
+        dprintf("> sockname sock=%d %s:%d\n",
+                data->fd, inet_ntoa(self.sin_addr), ntohs(self.sin_port));
+    }
+    k = sendto(data->fd, buf, n, data->flags, daddr, daddr_n);
+    dprintf("> sendto=%d\n", k);
+    return k;
+}
+
+/** Read from the underlying stream using recv();
+ *
+ * @param stream input
+ * @param buf where to put input
+ * @param n number of bytes to read
+ * @return number of bytes read
+ */
+static int socket_read(IOStream *s, void *buf, size_t n){
+    SocketData *data = socket_data(s);
+    int k;
+    struct sockaddr *saddr = (struct sockaddr *)&data->saddr;
+    socklen_t saddr_n = sizeof(data->saddr);
+    k = recvfrom(data->fd, buf, n, data->flags, saddr, &saddr_n);
+    return k;
+}
+
+/** Print to the underlying socket.
+ *
+ * @param s socket stream
+ * @param msg format to use
+ * @param args arguments
+ * @return result of the print
+ */
+static int socket_print(IOStream *s, const char *msg, va_list args){
+    SocketData *data = socket_data(s);
+    int n;
+    n = vsnprintf(data->buf, data->buf_n - 1, msg, args);
+    if(0 < n && n < data->buf_n){
+        socket_write(s, data->buf, n);
+    }
+    return n;
+}
+
+/** Read a character from the underlying socket
+ *
+ * @param s socket stream
+ * @return character read, IOSTREAM_EOF on end of socket (or error)
+ */
+static int socket_getc(IOStream *s){
+    char b;
+    int n, c;
+    n = socket_read(s, &b, 1);
+    c = (n <= 0 ? IOSTREAM_EOF : b);
+    return c;
+}
+
+/** Flush the socket (no-op).
+ *
+ * @param s socket stream
+ * @return 0 on success, error code otherwise
+ */
+static int socket_flush(IOStream *s){
+    return 0;
+}
+
+/** Check if a socket stream has an error (no-op).
+ *
+ * @param s socket stream
+ * @return 1 if has an error, 0 otherwise
+ */
+static int socket_error(IOStream *s){
+    // Read SOL_SOCKET/SO_ERROR ?
+    return 0;
+}
+
+/** Close a socket stream.
+ *
+ * @param s socket stream to close
+ * @return result of the close
+ */
+static int socket_close(IOStream *s){
+    SocketData *data = socket_data(s);
+    return close(data->fd);
+}
+
+/** Free a socket stream.
+ *
+ * @param s socket stream
+ */
+static void socket_free(IOStream *s){
+    SocketData *data = socket_data(s);
+    deallocate(data);
+}
+
+/** Create an IOStream for a socket.
+ *
+ * @param fd socket to wtap
+ * @return new IOStream using fd for i/o
+ */
+IOStream *socket_stream_new(int fd){
+    int err = -ENOMEM;
+    IOStream *io = NULL;
+    SocketData *data = NULL;
+
+    io = ALLOCATE(IOStream);
+    if(!io) goto exit;
+    io->methods = &socket_methods;
+    data = ALLOCATE(SocketData);
+    if(!data) goto exit;
+    io->data = data;
+    data->fd = fd;
+    data->buf_n = sizeof(data->buf);
+    err = 0;
+  exit:
+    if(err){
+        if(io){
+            if(data) deallocate(data);
+            deallocate(io);
+            io = NULL;
+        }
+    }
+    return io;
+}
+
diff --git a/tools/libxutil/socket_stream.h b/tools/libxutil/socket_stream.h
new file mode 100644 (file)
index 0000000..5b8515f
--- /dev/null
@@ -0,0 +1,54 @@
+/* $Id: socket_stream.h,v 1.2 2004/03/04 17:38:13 mjw Exp $ */
+/*
+ * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _XEN_LIB_SOCKET_STREAM_H_
+#define _XEN_LIB_SOCKET_STREAM_H_
+
+#ifndef __KERNEL__
+#include "iostream.h"
+#include <stdio.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/** Data associated with a socket stream. */
+typedef struct SocketData {
+    /** The socket file descriptor. */
+    int fd;
+    /** Source address from last read (recvfrom). */
+    struct sockaddr_in saddr;
+    /** Destination address for writes (sendto). */
+    struct sockaddr_in daddr;
+    /** Write flags (sendto). */
+    int flags;
+    /** Buffer size. */
+    int buf_n;
+    /** Buffer for formatted printing. */
+    char buf[1024];
+} SocketData;
+
+extern IOStream *socket_stream_new(int fd);
+extern int socket_stream_data(IOStream *io, SocketData **data);
+extern int socket_stream_check(IOStream *io);
+extern int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr);
+extern int socket_stream_set_flags(IOStream *io, int flags);
+
+#endif
+#endif /* !_XEN_LIB_SOCKET_STREAM_H_ */
diff --git a/tools/libxutil/string_stream.c b/tools/libxutil/string_stream.c
new file mode 100644 (file)
index 0000000..c3cf423
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2001, 2002 Hewlett-Packard Company.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/** @file
+ * IOStream subtype for input and output to strings.
+ * Usable from user or kernel code (with __KERNEL__ defined).
+ */
+
+#include "sys_string.h"
+#include "string_stream.h"
+#include "allocate.h"
+
+static int string_print(IOStream *io, const char *msg, va_list args);
+static int string_getc(IOStream *io);
+static int string_error(IOStream *io);
+static int string_close(IOStream *io);
+static void string_free(IOStream *io);
+
+/** Methods for a string stream. */
+static IOMethods string_methods = {
+    //print: string_print,
+    //getc:  string_getc,
+    error: string_error,
+    close: string_close,
+    free:  string_free,
+};
+
+/** Get the string stream state.
+ *
+ * @param io string stream
+ * @return state
+ */
+static inline StringData *get_string_data(IOStream *io){
+    return (StringData*)io->data;
+}
+
+/** Read a character from a string stream.
+ *
+ * @param io string stream
+ * @return character read, IOSTREAM_EOF if no more input
+ */
+static int string_getc(IOStream *io){
+    StringData *data = get_string_data(io);
+    int c = IOSTREAM_EOF;
+    char *s = data->in;
+
+    if(s && s < data->end){
+        c = (unsigned)*s;
+        data->in = s+1;
+    }
+    return c;
+}
+
+/** Print to a string stream.
+ * Formats the data to an internal buffer and prints it.
+ * The formatted data must fit into the internal buffer.
+ *
+ * @param io string stream
+ * @param format print format
+ * @param args print arguments
+ * @return result of the print
+ */
+static int string_print(IOStream *io, const char *msg, va_list args){
+    StringData *data = get_string_data(io);
+    int k = data->end - data->out;
+    int n = vsnprintf(data->out, k, (char*)msg, args);
+    if(n < 0 || n > k ){
+        n = k;
+        IOStream_close(io);
+    } else {
+        data->out += n;
+    }
+    return n;
+}
+
+/** Test if a string stream has an error.
+ *
+ * @param io string stream
+ * @return 0 if ok, error code otherwise
+ */
+static int string_error(IOStream *io){
+    StringData *data = get_string_data(io);
+    return data->out == NULL;
+}
+
+/** Close a string stream.
+ *
+ * @param io string stream
+ * @return 0
+ */
+static int string_close(IOStream *io){
+    StringData *data = get_string_data(io);
+    data->in = NULL;
+    data->out = NULL;
+    return 0;
+}
+
+/** Free a string stream.
+ * The stream must have been allocated, not statically created.
+ * The stream state is freed, but the underlying string is not.
+ *
+ * @param io string stream
+ */
+static void string_free(IOStream *io){
+    StringData *data = get_string_data(io);
+    zero(data, sizeof(*data));
+    deallocate(data);
+}
+
+/** Get the methods to use for a string stream.
+ *
+ * @return methods
+ */
+IOMethods *string_stream_get_methods(void){
+    return &string_methods;
+}
+
+/** Initialise a string stream, usually from static data.
+ *
+ * @param io address of IOStream to fill in
+ * @param data address of StringData to fill in
+ * @param s string to use
+ * @param n length of the string
+ */
+void string_stream_init(IOStream *io, StringData *data, char *s, int n){
+    if(data && io){
+        zero(data, sizeof(*data));
+        data->string = (char*)s;
+        data->in = data->string;
+        data->out = data->string;
+        data->size = n;
+        data->end = data->string + n;
+        zero(io, sizeof(*io));
+        io->methods = &string_methods;
+        io->data = data;
+    }
+}
+
+/** Allocate and initialise a string stream.
+ *
+ * @param s string to use
+ * @param n length of the string
+ * @return new stream (free using IOStream_free)
+ */
+IOStream *string_stream_new(char *s, int n){
+    int ok = 0;
+    StringData *data = ALLOCATE(StringData);
+    IOStream *io = ALLOCATE(IOStream);
+    if(data && io){
+        ok = 1;
+        string_stream_init(io, data, s, n);
+    }
+    if(!ok){
+        deallocate(data);
+        deallocate(io);
+        io = NULL;
+    }
+    return io;
+}
diff --git a/tools/libxutil/string_stream.h b/tools/libxutil/string_stream.h
new file mode 100644 (file)
index 0000000..36d764b
--- /dev/null
@@ -0,0 +1,46 @@
+/* $Id: string_stream.h,v 1.1 2003/08/22 14:25:48 mjw Exp $ */
+/*
+ * Copyright (C) 2001, 2002 Hewlett-Packard Company.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _SP_STRING_STREAM_H_
+#define _SP_STRING_STREAM_H_
+
+#include "iostream.h"
+
+/** Internal state for a string stream.
+ * Exposed here so that string streams can be statically created, using
+ * string_stream_init().
+ */
+typedef struct {
+    /** The string used for input and ouput. */
+    char *string;
+    /** Output pointer. */
+    char *out;
+    /** Input pointer. */
+    char *in;
+    /** Length of string. */
+    int size;
+    /** End marker. */
+    char *end;
+} StringData;
+
+extern IOMethods *string_stream_get_methods(void);
+extern IOStream *string_stream_new(char *s, int n);
+extern void string_stream_init(IOStream *stream, StringData *data, char *s, int n);
+
+#endif /* !_SP_STRING_STREAM_H_ */
diff --git a/tools/libxutil/sxpr.c b/tools/libxutil/sxpr.c
new file mode 100644 (file)
index 0000000..adeffbe
--- /dev/null
@@ -0,0 +1,935 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or  (at your option) any later version. This library is 
+ * distributed in the  hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <stdarg.h>
+#include "sys_string.h"
+#include "lexis.h"
+#include "sys_net.h"
+#include "hash_table.h"
+#include "sxpr.h"
+
+#include <errno.h>
+#undef free
+
+/** @file
+ * General representation of sxprs.
+ * Includes print, equal, and free functions for the sxpr types.
+ *
+ * Zero memory containing an Sxpr will have the value ONONE - this is intentional.
+ * When a function returning an sxpr cannot allocate memory we return ONOMEM.
+ *
+ */
+
+static int atom_print(IOStream *io, Sxpr obj, unsigned flags);
+static int atom_equal(Sxpr x, Sxpr y);
+static void atom_free(Sxpr obj);
+
+static int string_print(IOStream *io, Sxpr obj, unsigned flags);
+static int string_equal(Sxpr x, Sxpr y);
+static void string_free(Sxpr obj);
+
+static int cons_print(IOStream *io, Sxpr obj, unsigned flags);
+static int cons_equal(Sxpr x, Sxpr y);
+static void cons_free(Sxpr obj);
+
+static int null_print(IOStream *io, Sxpr obj, unsigned flags);
+static int none_print(IOStream *io, Sxpr obj, unsigned flags);
+static int int_print(IOStream *io, Sxpr obj, unsigned flags);
+static int bool_print(IOStream *io, Sxpr obj, unsigned flags);
+
+/** Type definitions. */
+static SxprType types[1024] = {
+    [T_NONE]     { type:    T_NONE,     name: "none",       print: none_print      },
+    [T_NULL]     { type:    T_NULL,     name: "null",       print: null_print      },
+    [T_UINT]     { type:    T_UINT,     name: "int",        print: int_print,      },
+    [T_BOOL]     { type:    T_BOOL,     name: "bool",       print: bool_print,     },
+    [T_ATOM]     { type:    T_ATOM,     name: "atom",       print: atom_print,
+                  pointer: TRUE,
+                  free:    atom_free,
+                  equal:   atom_equal,
+                },
+    [T_STRING]   { type:    T_STRING,   name: "string",     print: string_print,
+                  pointer: TRUE,
+                  free:    string_free,
+                  equal:   string_equal,
+                },
+    [T_CONS]     { type:    T_CONS,     name: "cons",       print: cons_print,
+                  pointer: TRUE,
+                  free:    cons_free,
+                  equal:   cons_equal,
+                },
+};
+
+/** Number of entries in the types array. */
+static int type_sup = sizeof(types)/sizeof(types[0]);
+
+/** Get the type definition for a given type code.
+ *
+ * @param ty type code
+ * @return type definition or null
+ */
+SxprType *get_sxpr_type(int ty){
+    if(0 <= ty && ty < type_sup){
+        return types+ty;
+    }
+    return NULL;
+}
+
+/** The default print function.
+ *
+ * @param io stream to print to
+ * @param x sxpr to print
+ * @param flags print flags
+ * @return number of bytes written on success
+ */
+int default_print(IOStream *io, Sxpr x, unsigned flags){
+    return IOStream_print(io, "#<%u %lu>\n", get_type(x), get_ul(x));
+}
+
+/** The default equal function.
+ * Uses eq().
+ *
+ * @param x sxpr to compare
+ * @param y sxpr to compare
+ * @return 1 if equal, 0 otherwise
+ */
+int default_equal(Sxpr x, Sxpr y){
+    return eq(x, y);
+}
+
+/** General sxpr print function.
+ * Prints an sxpr on a stream using the print function for the sxpr type.
+ * Printing is controlled by flags from the PrintFlags enum.
+ * If PRINT_TYPE is in the flags the sxpr type is printed before the sxpr
+ * (for debugging).
+ *
+ * @param io stream to print to
+ * @param x sxpr to print
+ * @param flags print flags
+ * @return number of bytes written
+ */
+int objprint(IOStream *io, Sxpr x, unsigned flags){
+    SxprType *def = get_sxpr_type(get_type(x));
+    ObjPrintFn *print_fn = (def && def->print ? def->print : default_print);
+    int k = 0;
+    if(!io) return k;
+    if(flags & PRINT_TYPE){
+       k += IOStream_print(io, "%s:", def->name);
+    }
+    k += print_fn(io, x, flags);
+    return k;
+}
+
+/** General sxpr free function.
+ * Frees an sxpr using the free function for its type.
+ * Free functions must recursively free any subsxprs.
+ * If no function is defined then the default is to
+ * free sxprs whose type has pointer true.
+ * Sxprs must not be used after freeing.
+ *
+ * @param x sxpr to free
+ */
+void objfree(Sxpr x){
+    SxprType *def = get_sxpr_type(get_type(x));
+
+    if(def){
+       if(def->free){
+           def->free(x);
+       } else if (def->pointer){
+           hfree(x);
+       }
+    }
+}
+
+/** General sxpr equality function.
+ * Compares x and y using the equal function for x.
+ * Uses default_equal() if x has no equal function.
+ *
+ * @param x sxpr to compare
+ * @param y sxpr to compare
+ * @return 1 if equal, 0 otherwise
+ */
+int objequal(Sxpr x, Sxpr y){
+    SxprType *def = get_sxpr_type(get_type(x));
+    ObjEqualFn *equal_fn = (def && def->equal ? def->equal : default_equal);
+    return equal_fn(x, y);
+}
+
+/** Search for a key in an alist.
+ * An alist is a list of conses, where the cars
+ * of the conses are the keys. Compares keys using equality.
+ *
+ * @param k key
+ * @param l alist to search
+ * @return first element of l with car k, or ONULL
+ */
+Sxpr assoc(Sxpr k, Sxpr l){
+    for( ; CONSP(l) ; l = CDR(l)){
+        Sxpr x = CAR(l);
+        if(CONSP(x) && objequal(k, CAR(x))){
+            return x;   
+        }
+    }
+    return ONULL;
+}
+
+/** Search for a key in an alist.
+ * An alist is a list of conses, where the cars
+ * of the conses are the keys. Compares keys using eq.
+ *
+ * @param k key
+ * @param l alist to search
+ * @return first element of l with car k, or ONULL
+ */
+Sxpr assocq(Sxpr k, Sxpr l){
+    for( ; CONSP(l); l = CDR(l)){
+        Sxpr x = CAR(l);
+        if(CONSP(x) && eq(k, CAR(x))){
+            return x;
+        }
+    }
+    return ONULL;
+}
+
+/** Add a new key and value to an alist.
+ *
+ * @param k key
+ * @param l value
+ * @param l alist
+ * @return l with the new cell added to the front
+ */
+Sxpr acons(Sxpr k, Sxpr v, Sxpr l){
+    Sxpr x, y;
+    x = cons_new(k, v);
+    if(NOMEMP(x)) return x;
+    y = cons_new(x, l);
+    if(NOMEMP(y)) cons_free_cells(x);
+    return y;
+}
+
+/** Test if a list contains an element.
+ * Uses sxpr equality.
+ *
+ * @param l list
+ * @param x element to look for
+ * @return a tail of l with x as car, or ONULL
+ */
+Sxpr cons_member(Sxpr l, Sxpr x){
+    for( ; CONSP(l) && !eq(x, CAR(l)); l = CDR(l)){}
+    return l;
+}
+
+/** Test if a list contains an element satisfying a test.
+ * The test function is called with v and an element of the list.
+ *
+ * @param l list
+ * @param test_fn test function to use
+ * @param v value for first argument to the test
+ * @return a tail of l with car satisfying the test, or 0
+ */
+Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
+    for( ; CONSP(l) && !test_fn(v, CAR(l)); l = CDR(l)){ }
+    return l;
+}
+
+/** Test if the elements of list 't' are a subset of the elements
+ * of list 's'. Element order is not significant.
+ *
+ * @param s element list to check subset of
+ * @param t element list to check if is a subset
+ * @return 1 if is a subset, 0 otherwise
+ */
+int cons_subset(Sxpr s, Sxpr t){
+    for( ; CONSP(t); t = CDR(t)){
+       if(!CONSP(cons_member(s, CAR(t)))){
+           return 0;
+       }
+    }
+    return 1;
+}
+
+/** Test if two lists have equal sets of elements.
+ * Element order is not significant.
+ *
+ * @param s list to check
+ * @param t list to check
+ * @return 1 if equal, 0 otherwise
+ */
+int cons_set_equal(Sxpr s, Sxpr t){
+    return cons_subset(s, t) && cons_subset(t, s);
+}
+
+#ifdef USE_GC
+/*============================================================================*/
+/* The functions inside this ifdef are only safe if GC is used.
+ * Otherwise they may leak memory.
+ */
+
+/** Remove an element from a list (GC only).
+ * Uses sxpr equality and removes all instances, even
+ * if there are more than one.
+ *
+ * @param l list to remove elements from
+ * @param x element to remove
+ * @return modified input list
+ */
+Sxpr cons_remove(Sxpr l, Sxpr x){
+    return cons_remove_if(l, eq, x);
+}
+
+/** Remove elements satisfying a test (GC only).
+ * The test function is called with v and an element of the set.
+ *
+ * @param l list to remove elements from
+ * @param test_fn function to use to decide if an element should be removed
+ * @return modified input list
+ */
+Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
+    Sxpr prev = ONULL, elt, next;
+
+    for(elt = l; CONSP(elt); elt = next){
+        next = CDR(elt);
+        if(test_fn(v, CAR(elt))){
+            if(NULLP(prev)){
+                l = next;
+            } else {
+                CDR(prev) = next;
+            }
+        }
+    }
+    return l;
+}
+
+/** Set the value for a key in an alist (GC only).
+ * If the key is present, changes the value, otherwise
+ * adds a new cell.
+ *
+ * @param k key
+ * @param v value
+ * @param l alist
+ * @return modified or extended list
+ */
+Sxpr setf(Sxpr k, Sxpr v, Sxpr l){
+    Sxpr e = assoc(k, l);
+    if(NULLP(e)){
+        l = acons(k, v, l);
+    } else {
+        CAR(CDR(e)) = v;
+    }
+    return l;
+}
+/*============================================================================*/
+#endif /* USE_GC */
+
+/** Create a new atom with the given name.
+ *
+ * @param name the name
+ * @return new atom
+ */
+Sxpr atom_new(char *name){
+    Sxpr n, obj = ONOMEM;
+
+    n = string_new(name);
+    if(NOMEMP(n)) goto exit;
+    obj = HALLOC(ObjAtom, T_ATOM);
+    if(NOMEMP(obj)) goto exit;
+    OBJ_ATOM(obj)->name = n;
+  exit:
+    return obj;
+}
+
+/** Free an atom.
+ *
+ * @param obj to free
+ */
+void atom_free(Sxpr obj){
+    // Interned atoms are shared, so do not free.
+    if(OBJ_ATOM(obj)->interned) return;
+    objfree(OBJ_ATOM(obj)->name);
+    hfree(obj);
+}
+
+/** Print an atom. Prints the atom name.
+ *
+ * @param io stream to print to
+ * @param obj to print
+ * @param flags print flags
+ * @return number of bytes printed
+ */
+int atom_print(IOStream *io, Sxpr obj, unsigned flags){
+    //return string_print(io, OBJ_ATOM(obj)->name, (flags | PRINT_RAW));
+    return string_print(io, OBJ_ATOM(obj)->name, flags);
+}
+
+/** Atom equality.
+ *
+ * @param x to compare
+ * @param y to compare
+ * @return 1 if equal, 0 otherwise
+ */
+int atom_equal(Sxpr x, Sxpr y){
+    int ok;
+    ok = eq(x, y);
+    if(ok) goto exit;
+    ok = ATOMP(y) && string_equal(OBJ_ATOM(x)->name, OBJ_ATOM(y)->name);
+    if(ok) goto exit;
+    ok = STRINGP(y) && string_equal(OBJ_ATOM(x)->name, y);
+  exit:
+    return ok;
+}
+
+/** Get the name of an atom.
+ *
+ * @param obj atom
+ * @return name
+ */
+char * atom_name(Sxpr obj){
+    return string_string(OBJ_ATOM(obj)->name);
+}
+
+/** Get the C string from a string sxpr.
+ *
+ * @param obj string sxpr
+ * @return string
+ */
+char * string_string(Sxpr obj){
+    return OBJ_STRING(obj);
+}
+
+/** Get the length of a string.
+ *
+ * @param obj string
+ * @return length
+ */
+int string_length(Sxpr obj){
+    return strlen(OBJ_STRING(obj));
+}
+
+/** Create a new string. The input string is copied,
+ * and must be null-terminated.
+ *
+ * @param s characters to put in the string
+ * @return new sxpr
+ */
+Sxpr string_new(char *s){
+    int n = (s ? strlen(s) : 0);
+    Sxpr obj;
+    obj = halloc(n+1, T_STRING);
+    if(!NOMEMP(obj)){
+        char *str = OBJ_STRING(obj);
+        strncpy(str, s, n);
+        str[n] = '\0';
+    }
+    return obj;
+}
+
+/** Free a string.
+ *
+ * @param obj to free
+ */
+void string_free(Sxpr obj){
+    hfree(obj);
+}
+
+/** Determine if a string needs escapes when printed
+ * using the given flags.
+ *
+ * @param str string to check
+ * @param flags print flags
+ * @return 1 if needs escapes, 0 otherwise
+ */
+int needs_escapes(char *str, unsigned flags){
+    char *c;
+    int val = 0;
+
+    if(str){
+       for(c=str; *c; c++){
+           if(in_alpha_class(*c)) continue;
+           if(in_decimal_digit_class(*c)) continue;
+           if(in_class(*c, "/._+:@~-")) continue;
+           val = 1;
+           break;
+       }
+    }
+    //printf("\n> val=%d str=|%s|\n", val, str);
+    return val;
+}
+
+/** Print a string to a stream, with escapes if necessary.
+ *
+ * @param io stream to print to
+ * @param str string
+ * @param flags print flags
+ * @return number of bytes written
+ */
+int _string_print(IOStream *io, char *str, unsigned flags){
+    int k = 0;
+    if((flags & PRINT_RAW) || !needs_escapes(str, flags)){
+        k += IOStream_print(io, str);
+    } else {
+       k += IOStream_print(io, "\"");
+       if(str){
+            char *s;
+            for(s = str; *s; s++){
+                if(*s < ' ' || *s >= 127 ){
+                    switch(*s){
+                    case '\a': k += IOStream_print(io, "\\a");  break;
+                    case '\b': k += IOStream_print(io, "\\b");  break;
+                    case '\f': k += IOStream_print(io, "\\f");  break;
+                    case '\n': k += IOStream_print(io, "\\n");  break;
+                    case '\r': k += IOStream_print(io, "\\r");  break;
+                    case '\t': k += IOStream_print(io, "\\t");  break;
+                    case '\v': k += IOStream_print(io, "\\v");  break;
+                    default:
+                        // Octal escape;
+                        k += IOStream_print(io, "\\%o", *s);
+                        break;
+                    }
+                } else if(*s == c_double_quote ||
+                          *s == c_single_quote ||
+                          *s == c_escape){
+                    k += IOStream_print(io, "\\%c", *s);
+                } else {
+                    k+= IOStream_print(io, "%c", *s);
+                }
+            }
+       }
+       k += IOStream_print(io, "\"");
+    }
+    return k;
+}
+
+/** Print a string to a stream, with escapes if necessary.
+ *
+ * @param io stream to print to
+ * @param obj string
+ * @param flags print flags
+ * @return number of bytes written
+ */
+int string_print(IOStream *io, Sxpr obj, unsigned flags){
+    return _string_print(io, OBJ_STRING(obj), flags);
+}
+
+/** Compare an sxpr with a string for equality.
+ *
+ * @param x string to compare with
+ * @param y sxpr to compare
+ * @return 1 if equal, 0 otherwise
+ */
+int string_equal(Sxpr x, Sxpr y){
+    int ok = 0;
+    ok = eq(x,y);
+    if(ok) goto exit;
+    ok = has_type(y, T_STRING) && !strcmp(OBJ_STRING(x), OBJ_STRING(y));
+    if(ok) goto exit;
+    ok = has_type(y, T_ATOM) && !strcmp(OBJ_STRING(x), atom_name(y));
+  exit:
+    return ok;
+}
+
+/** Create a new cons cell.
+ * The cell is ONOMEM if either argument is.
+ *
+ * @param car sxpr for the car
+ * @param cdr sxpr for the cdr
+ * @return new cons
+ */
+Sxpr cons_new(Sxpr car, Sxpr cdr){
+    Sxpr obj;
+    if(NOMEMP(car) || NOMEMP(cdr)){
+        obj = ONOMEM;
+    } else {
+        obj = HALLOC(ObjCons, T_CONS);
+        if(!NOMEMP(obj)){
+            ObjCons *z = OBJ_CONS(obj);
+            z->car = car;
+            z->cdr = cdr;
+        }
+    }
+    return obj;
+}
+
+/** Push a new element onto a list.
+ *
+ * @param list list to add to
+ * @param elt element to add
+ * @return 0 if successful, error code otherwise
+ */
+int cons_push(Sxpr *list, Sxpr elt){
+    Sxpr l;
+    l = cons_new(elt, *list);
+    if(NOMEMP(l)) return -ENOMEM;
+    *list = l;
+    return 0;
+}
+
+/** Free a cons. Recursively frees the car and cdr.
+ *
+ * @param obj to free
+ */
+void cons_free(Sxpr obj){
+    Sxpr next;
+    for(; CONSP(obj); obj = next){
+       next = CDR(obj);
+       objfree(CAR(obj));
+       hfree(obj);
+    }
+    if(!NULLP(obj)){
+       objfree(obj);
+    }
+}
+
+/** Free a cons and its cdr cells, but not the car sxprs.
+ * Does nothing if called on something that is not a cons.
+ *
+ * @param obj to free
+ */
+void cons_free_cells(Sxpr obj){
+    Sxpr next;
+    for(; CONSP(obj); obj = next){
+       next = CDR(obj);
+       hfree(obj);
+    }
+}
+
+/** Print a cons.
+ * Prints the cons in list format if the cdrs are conses.
+ * uses pair (dot) format if the last cdr is not a cons (or null).
+ *
+ * @param io stream to print to
+ * @param obj to print
+ * @param flags print flags
+ * @return number of bytes written
+ */
+int cons_print(IOStream *io, Sxpr obj, unsigned flags){
+    int first = 1;
+    int k = 0;
+    k += IOStream_print(io, "(");
+    for( ; CONSP(obj) ; obj = CDR(obj)){
+        if(first){ 
+            first = 0;
+        } else {
+            k += IOStream_print(io, " ");
+        }
+        k += objprint(io, CAR(obj), flags);
+    }
+    if(!NULLP(obj)){
+        k += IOStream_print(io, " . ");
+        k += objprint(io, obj, flags);
+    }
+    k += IOStream_print(io, ")");
+    return (IOStream_error(io) ? -1 : k);
+}
+
+/** Compare a cons with another sxpr for equality.
+ * If y is a cons, compares the cars and cdrs recursively.
+ *
+ * @param x cons to compare
+ * @param y sxpr to compare
+ * @return 1 if equal, 0 otherwise
+ */
+int cons_equal(Sxpr x, Sxpr y){
+    return CONSP(y) &&
+        objequal(CAR(x), CAR(y)) &&
+        objequal(CDR(x), CDR(y));
+}
+
+/** Return the length of a cons list.
+ *
+ * @param obj list
+ * @return length
+ */
+int cons_length(Sxpr obj){
+    int count = 0;
+    for( ; CONSP(obj); obj = CDR(obj)){
+        count++;
+    }
+    return count;
+}
+
+/** Destructively reverse a cons list in-place.
+ * If the argument is not a cons it is returned unchanged.
+ * 
+ * @param l to reverse
+ * @return reversed list
+ */
+Sxpr nrev(Sxpr l){
+    if(CONSP(l)){
+       // Iterate down the cells in the list making the cdr of
+       // each cell point to the previous cell. The last cell 
+       // is the head of the reversed list.
+       Sxpr prev = ONULL;
+       Sxpr cell = l;
+       Sxpr next;
+
+       while(1){
+           next = CDR(cell);
+           CDR(cell) = prev;
+           if(!CONSP(next)) break;
+           prev = cell;
+           cell = next;
+       }
+       l = cell;
+    }
+    return l;
+}
+
+/** Print the null sxpr.       
+ *
+ * @param io stream to print to
+ * @param obj to print
+ * @param flags print flags
+ * @return number of bytes written
+ */
+static int null_print(IOStream *io, Sxpr obj, unsigned flags){
+    return IOStream_print(io, "()");
+}
+
+/** Print the `unspecified' sxpr none.
+ *
+ * @param io stream to print to
+ * @param obj to print
+ * @param flags print flags
+ * @return number of bytes written
+ */
+static int none_print(IOStream *io, Sxpr obj, unsigned flags){
+    return IOStream_print(io, "<none>");
+}
+
+/** Print an integer.
+ *
+ * @param io stream to print to
+ * @param obj to print
+ * @param flags print flags
+ * @return number of bytes written
+ */
+static int int_print(IOStream *io, Sxpr obj, unsigned flags){
+    return IOStream_print(io, "%d", OBJ_INT(obj));
+}
+
+/** Print a boolean.
+ *
+ * @param io stream to print to
+ * @param obj to print
+ * @param flags print flags
+ * @return number of bytes written
+ */
+static int bool_print(IOStream *io, Sxpr obj, unsigned flags){
+    return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false));
+}
+
+int sxprp(Sxpr obj, Sxpr name){
+    return CONSP(obj) && objequal(CAR(obj), name);
+}
+
+/** Get the name of an element.
+ * 
+ * @param obj element
+ * @return name
+ */
+Sxpr sxpr_name(Sxpr obj){
+    Sxpr val = ONONE;
+    if(CONSP(obj)){
+        val = CAR(obj);
+    } else if(STRINGP(obj) || ATOMP(obj)){
+        val = obj;
+    }
+    return val;
+}
+
+int sxpr_is(Sxpr obj, char *s){
+    if(ATOMP(obj)) return !strcmp(atom_name(obj), s);
+    if(STRINGP(obj)) return !strcmp(string_string(obj), s);
+    return 0;
+}
+
+int sxpr_elementp(Sxpr obj, Sxpr name){
+    return CONSP(obj) && objequal(CAR(obj), name);
+}
+
+/** Get the attributes of an sxpr.
+ * 
+ * @param obj sxpr
+ * @return attributes
+ */
+Sxpr sxpr_attributes(Sxpr obj){
+    Sxpr val = ONULL;
+    if(CONSP(obj)){
+        obj = CDR(obj);
+        if(CONSP(obj)){
+            obj = CAR(obj);
+            if(sxprp(obj, intern("@"))){
+                val = CDR(obj);
+            }
+        }
+    }
+    return val;
+}
+
+Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def){
+    Sxpr val = ONONE;
+    val = assoc(sxpr_attributes(obj), key);
+    if(CONSP(val) && CONSP(CDR(val))){
+        val = CADR(def);
+    } else {
+        val = def;
+    }
+    return val;
+}
+
+/** Get the children of an sxpr.
+ * 
+ * @param obj sxpr
+ * @return children
+ */
+Sxpr sxpr_children(Sxpr obj){
+    Sxpr val = ONULL;
+    if(CONSP(obj)){
+        val = CDR(obj);
+        if(CONSP(val) && sxprp(CAR(val), intern("@"))){
+            val = CDR(val);
+        }
+    }
+    return val;
+}
+
+Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def){
+    Sxpr val = ONONE;
+    Sxpr l;
+    for(l = sxpr_children(obj); CONSP(l); l = CDR(l)){
+        if(sxprp(CAR(l), name)){
+            val = CAR(l);
+            break;
+        }
+    }
+    if(NONEP(val)) val = def;
+    return val;
+}
+
+Sxpr sxpr_child0(Sxpr obj, Sxpr def){
+    Sxpr val = ONONE;
+    Sxpr l = sxpr_children(obj);
+    if(CONSP(l)){
+        val = CAR(l);
+    } else {
+        val = def;
+    }
+    return val;
+}
+
+Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def){
+    Sxpr val = ONONE;
+    val = sxpr_child(obj, name, ONONE);
+    if(NONEP(val)){
+        val = def;
+    } else {
+        val = sxpr_child0(val, def);
+    }
+    return val;
+}
+
+/** Table of interned symbols. Indexed by symbol name. */
+static HashTable *symbols = NULL;
+
+/** Hash function for entries in the symbol table.
+ *
+ * @param key to hash
+ * @return hashcode
+ */
+static Hashcode sym_hash_fn(void *key){
+    return hash_string((char*)key);
+}
+
+/** Key equality function for the symbol table.
+ *
+ * @param x to compare
+ * @param y to compare
+ * @return 1 if equal, 0 otherwise
+ */
+static int sym_equal_fn(void *x, void *y){
+    return !strcmp((char*)x, (char*)y);
+}
+
+/** Entry free function for the symbol table.
+ *
+ * @param table the entry is in
+ * @param entry being freed
+ */
+static void sym_free_fn(HashTable *table, HTEntry *entry){
+    if(entry){
+       objfree(((ObjAtom*)entry->value)->name);
+       HTEntry_free(entry);
+    }
+}
+       
+/** Initialize the symbol table.
+ *
+ * @return 0 on sucess, error code otherwise
+ */
+static int init_symbols(void){
+    symbols = HashTable_new(100);
+    if(symbols){
+        symbols->key_hash_fn = sym_hash_fn;
+        symbols->key_equal_fn = sym_equal_fn;
+       symbols->entry_free_fn = sym_free_fn;
+        return 0;
+    }
+    return -1;
+}
+
+/** Cleanup the symbol table. Frees the table and all its symbols.
+ */
+void cleanup_symbols(void){
+    HashTable_free(symbols);
+    symbols = NULL;
+}
+
+/** Get the interned symbol with the given name.
+ * No new symbol is created.
+ *
+ * @return symbol or null
+ */
+Sxpr get_symbol(char *sym){
+    HTEntry *entry;
+    if(!symbols){
+       if(init_symbols()) return ONOMEM;
+       return ONULL;
+    }
+    entry = HashTable_get_entry(symbols, sym);
+    if(entry){
+        return OBJP(T_ATOM, entry->value);
+    } else {
+        return ONULL;
+    }
+}
+
+/** Get the interned symbol with the given name.
+ * Creates a new symbol if necessary.
+ *
+ * @return symbol
+ */
+Sxpr intern(char *sym){
+    Sxpr symbol = get_symbol(sym);
+    if(NULLP(symbol)){
+       if(!symbols) return ONOMEM;
+        symbol = atom_new(sym);
+        if(!NOMEMP(symbol)){
+           OBJ_ATOM(symbol)->interned = TRUE;
+            HashTable_add(symbols, atom_name(symbol), get_ptr(symbol));
+        }
+    }
+    return symbol;
+}
diff --git a/tools/libxutil/sxpr.h b/tools/libxutil/sxpr.h
new file mode 100644 (file)
index 0000000..b900831
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or  (at your option) any later version. This library is 
+ * distributed in the  hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+#ifndef _XEN_LIB_SXPR_H_
+#define _XEN_LIB_SXPR_H_
+
+#include <stdint.h>
+
+#include "hash_table.h"
+#include "iostream.h"
+#include "allocate.h"
+
+/** @file
+ * Definitions for rules and sxprs.
+ */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/** Sxpr type. */
+typedef int16_t TypeCode;
+
+/** A typed sxpr handle.*/
+typedef struct Sxpr {
+    /** Sxpr type. */
+    TypeCode type;
+    union {
+       /** Sxpr value. */
+        unsigned long ul;
+       /** Pointer. */
+        void *ptr;
+    } v;
+} Sxpr;
+
+/** Sxpr type to indicate out of memory. */
+#define T_NOMEM      ((TypeCode)-1)
+/** The 'unspecified' sxpr. */
+#define T_NONE       ((TypeCode)0)
+/** The empty list. */
+#define T_NULL       ((TypeCode)1)
+/** Unsigned integer. */
+#define T_UINT       ((TypeCode)2)
+/** A string. */
+#define T_STRING     ((TypeCode)3)
+/** An atom. */
+#define T_ATOM       ((TypeCode)4)
+/** A boolean. */
+#define T_BOOL       ((TypeCode)5)
+
+/** A cons (pair or list). */
+#define T_CONS       ((TypeCode)10)
+
+/** An error. */
+#define T_ERR        ((TypeCode)40)
+
+/** An atom. */
+typedef struct ObjAtom {
+    Sxpr name;
+    Hashcode hashcode;
+    int interned;
+} ObjAtom;
+
+/** A cons (pair). */
+typedef struct ObjCons {
+    Sxpr car;
+    Sxpr cdr;
+} ObjCons;
+
+/** A vector. */
+typedef struct ObjVector {
+    int n;
+    Sxpr data[0];
+} ObjVector;
+
+/** Flags for sxpr printing. */
+enum PrintFlags {
+    PRINT_RAW           = 0x001,
+    PRINT_TYPE          = 0x002,
+    PRINT_PRETTY        = 0x004,
+    PRINT_NUM           = 0x008,
+};
+
+/** An integer sxpr.
+ *
+ * @param ty type
+ * @param val integer value
+ */
+#define OBJI(ty, val) (Sxpr){ type: (ty), v: { ul: (val) }}
+
+/** A pointer sxpr.
+ * If the pointer is non-null, returns an sxpr containing it.
+ * If the pointer is null, returns ONOMEM.
+ *
+ * @param ty type
+ * @param val pointer
+ */
+#define OBJP(ty, val) ((val) ? (Sxpr){ type: (ty), v: { ptr: (val) }} : ONOMEM)
+
+/** Make an integer sxpr containing a pointer.
+ *
+ * @param val pointer
+ */
+#define PTR(val) OBJP(T_UINT, (void*)(val))
+
+/** Make an integer sxpr.
+ * @param x value
+ */
+#define OINT(x)       OBJI(T_UINT,  x)
+
+/** Make an error sxpr.
+ *
+ * @param x value
+ */
+#define OERR(x)       OBJI(T_ERR,   x)
+
+/** Out of memory constant. */
+#define ONOMEM        OBJI(T_NOMEM, 0)
+
+/** The `unspecified' constant. */
+#define ONONE         OBJI(T_NONE,  0)
+
+/** Empty list constant. */
+#define ONULL         OBJI(T_NULL,  0)
+
+/** False constant. */
+#define OFALSE        OBJI(T_BOOL,  0)
+
+/** True constant. */
+#define OTRUE         OBJI(T_BOOL,  1)
+
+/* Recognizers for the various sxpr types.  */
+#define ATOMP(obj)        has_type(obj, T_ATOM)
+#define BOOLP(obj)        has_type(obj, T_BOOL)
+#define CONSP(obj)        has_type(obj, T_CONS)
+#define ERRP(obj)         has_type(obj, T_ERR)
+#define INTP(obj)         has_type(obj, T_UINT)
+#define NOMEMP(obj)       has_type(obj, T_NOMEM)
+#define NONEP(obj)        has_type(obj, T_NONE)
+#define NULLP(obj)        has_type(obj, T_NULL)
+#define STRINGP(obj)      has_type(obj, T_STRING)
+
+#define TRUEP(obj)    get_ul(obj)
+
+/** Convert an sxpr to an unsigned integer. */
+#define OBJ_UINT(x)   get_ul(x)
+/** Convert an sxpr to an integer. */
+#define OBJ_INT(x)    (int)get_ul(x)
+
+/* Conversions of sxprs to their values.
+ * No checking is done.
+ */
+#define OBJ_STRING(x)  ((char*)get_ptr(x))
+#define OBJ_CONS(x)    ((ObjCons*)get_ptr(x))
+#define OBJ_ATOM(x)    ((ObjAtom*)get_ptr(x))
+#define OBJ_SET(x)     ((ObjSet*)get_ptr(x))
+#define CAR(x)         (OBJ_CONS(x)->car)
+#define CDR(x)         (OBJ_CONS(x)->cdr)
+
+#define CAAR(x)        (CAR(CAR(x)))
+#define CADR(x)        (CAR(CDR(x)))
+#define CDAR(x)        (CDR(CAR(x)))
+#define CDDR(x)        (CDR(CDR(x)))
+
+/** Get the integer value from an sxpr.
+ *
+ * @param obj sxpr
+ * @return value
+ */
+static inline unsigned long get_ul(Sxpr obj){
+    return obj.v.ul;
+}
+
+/** Get the pointer value from an sxpr.
+ *
+ * @param obj sxpr
+ * @return value
+ */
+static inline void * get_ptr(Sxpr obj){
+    return obj.v.ptr;
+}
+
+/** Create an sxpr containing a pointer.
+ *
+ * @param type typecode
+ * @param val pointer
+ * @return sxpr
+ */
+static inline Sxpr obj_ptr(TypeCode type, void *val){
+    return (Sxpr){ type: type, v: { ptr: val } };
+}
+
+/** Create an sxpr containing an integer.
+ *
+ * @param type typecode
+ * @param val integer
+ * @return sxpr
+ */
+static inline Sxpr obj_ul(TypeCode type, unsigned long val){
+    return (Sxpr){ type: type, v: { ul: val } };
+}
+
+/** Get the type of an sxpr.
+ *
+ * @param obj sxpr
+ * @return type
+ */
+static inline TypeCode get_type(Sxpr obj){
+    return obj.type;
+}
+
+/** Check the type of an sxpr.
+ *
+ * @param obj sxpr
+ * @param type to check
+ * @return 1 if has the type, 0 otherwise
+ */
+static inline int has_type(Sxpr obj, TypeCode type){
+    return get_type(obj) == type;
+}
+
+/** Compare sxprs for literal equality of type and value.
+ *
+ * @param x sxpr to compare
+ * @param y sxpr to compare
+ * @return 1 if equal, 0 otherwise
+ */
+static inline int eq(Sxpr x, Sxpr y){
+    return ((get_type(x) == get_type(y)) && (get_ul(x) == get_ul(y)));
+}
+
+/** Checked version of CAR
+ *
+ * @param x sxpr
+ * @return CAR if a cons, x otherwise
+ */
+static inline Sxpr car(Sxpr x){
+    return (CONSP(x) ? CAR(x) : x);
+}
+
+/** Checked version of CDR.
+ *
+ * @param x sxpr
+ * @return CDR if a cons, null otherwise
+ */
+static inline Sxpr cdr(Sxpr x){
+    return (CONSP(x) ? CDR(x) : ONULL);
+}
+
+/** Allocate some memory and return an sxpr containing it.
+ * Returns ONOMEM if allocation failed.
+ *
+ * @param n number of bytes to allocate
+ * @param ty typecode
+ * @return sxpr
+ */
+static inline Sxpr halloc(size_t n,  TypeCode ty){
+    return OBJP(ty, allocate(n));
+}
+
+/** Allocate an sxpr containing a pointer to the given type.
+ *
+ * @param ty type (uses sizeof to determine how many bytes to allocate)
+ * @param code typecode
+ * @return sxpr, ONOMEM if allocation failed
+ */
+#define HALLOC(ty, code) halloc(sizeof(ty), code)
+
+typedef int ObjPrintFn(IOStream *io, Sxpr obj, unsigned flags);
+typedef int ObjEqualFn(Sxpr obj, Sxpr other);
+typedef void ObjFreeFn(Sxpr obj);
+
+/** An sxpr type definition. */
+typedef struct SxprType {
+    TypeCode type;
+    char *name;
+    int pointer;
+    ObjPrintFn *print;
+    ObjEqualFn *equal;
+    ObjFreeFn *free;
+} SxprType;
+
+
+extern SxprType *get_sxpr_type(int ty);
+
+/** Free the pointer in an sxpr.
+ *
+ * @param x sxpr containing a pointer
+ */
+static inline void hfree(Sxpr x){
+    deallocate(get_ptr(x));
+}
+
+extern int objprint(IOStream *io, Sxpr x, unsigned flags);
+extern int objequal(Sxpr x, Sxpr y);
+extern void objfree(Sxpr x);
+
+extern void cons_free_cells(Sxpr obj);
+extern Sxpr intern(char *s);
+
+extern Sxpr assoc(Sxpr k, Sxpr l);
+extern Sxpr assocq(Sxpr k, Sxpr l);
+extern Sxpr acons(Sxpr k, Sxpr v, Sxpr l);
+extern Sxpr nrev(Sxpr l);
+extern Sxpr cons_member(Sxpr l, Sxpr x);
+extern Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
+extern int cons_subset(Sxpr s, Sxpr t);
+extern int cons_set_equal(Sxpr s, Sxpr t);
+
+#ifdef USE_GC
+extern Sxpr cons_remove(Sxpr l, Sxpr x);
+extern Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
+#endif
+
+extern Sxpr atom_new(char *name);
+extern char * atom_name(Sxpr obj);
+
+extern Sxpr string_new(char *s);
+extern char * string_string(Sxpr obj);
+extern int string_length(Sxpr obj);
+
+extern Sxpr cons_new(Sxpr car, Sxpr cdr);
+extern int cons_push(Sxpr *list, Sxpr elt);
+extern int cons_length(Sxpr obj);
+
+Sxpr sxpr_name(Sxpr obj);
+int sxpr_is(Sxpr obj, char *s);
+int sxpr_elementp(Sxpr obj, Sxpr name);
+Sxpr sxpr_attributes(Sxpr obj);
+Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def);
+Sxpr sxpr_children(Sxpr obj);
+Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def);
+Sxpr sxpr_child0(Sxpr obj, Sxpr def);
+Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def);
+
+/** Create a new atom.
+ *
+ * @param s atom name
+ * @return new atom
+ */
+static inline Sxpr mkatom(char *s){
+    return atom_new(s);
+}
+
+/** Create a new string sxpr.
+ *
+ * @param s string bytes (copied)
+ * @return new string
+ */
+static inline Sxpr mkstring(char *s){
+    return string_new(s);
+}
+
+/** Create an integer sxpr.
+ *
+ * @param i value
+ * @return sxpr
+ */
+static inline Sxpr mkint(int i){
+    return OBJI(T_UINT, i);
+}
+
+/** Create a boolean sxpr.
+ *
+ * @param b value
+ * @return sxpr
+ */
+static inline Sxpr mkbool(int b){
+    return OBJI(T_BOOL, (b ? 1 : 0));
+}
+
+/* Constants used in parsing and printing. */
+#define k_list_open    "("
+#define c_list_open    '('
+#define k_list_close   ")"
+#define c_list_close   ')'
+#define k_true         "true"
+#define k_false        "false"
+
+#define c_var          '$'
+#define c_escape       '\\'
+#define c_single_quote '\''
+#define c_double_quote '"'
+#define c_string_open  c_double_quote
+#define c_string_close c_double_quote
+#define c_data_open    '['
+#define c_data_close   ']'
+#define c_binary       '*'
+#define c_eval         '!'
+#define c_concat_open  '{'
+#define c_concat_close '}'
+
+#endif /* ! _XEN_LIB_SXPR_H_ */
diff --git a/tools/libxutil/sxpr_parser.c b/tools/libxutil/sxpr_parser.c
new file mode 100644 (file)
index 0000000..16fec56
--- /dev/null
@@ -0,0 +1,897 @@
+
+#ifdef __KERNEL__
+#  include <linux/config.h>
+#  include <linux/module.h>
+#  include <linux/kernel.h>
+#  include <linux/string.h>
+#  include <linux/errno.h>
+#else
+#  include <stdlib.h>
+#  include <errno.h>
+#endif
+
+#include "iostream.h"
+#include "lexis.h"
+#include "sxpr_parser.h"
+#include "sys_string.h"
+
+/** @file
+ * Sxpr parsing.
+ *
+ * So that the parser does not leak memory, all sxprs constructed by
+ * the parser must be freed on error.  On successful parse the sxpr
+ * returned becomes the responsibility of the caller.
+ *
+ * @author Mike Wray <mike.wray@hpl.hp.com>
+ */
+
+#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
+#define printf(fmt, args...)   IOStream_print(iostdout, fmt, ##args)
+
+static void reset(Parser *z);
+static int inputchar(Parser *p, char c);
+static int savechar(Parser *p, char c);
+extern void parse_error(Parser *in);
+extern void parse_error_id(Parser *in, ParseErrorId id);
+
+static int begin_start(Parser *p, char c);
+static int state_start(Parser *p, char c);
+static int end_start(Parser *p);
+
+static int begin_comment(Parser *p, char c);
+static int state_comment(Parser *p, char c);
+static int end_comment(Parser *p);
+
+static int begin_string(Parser *p, char c);
+static int state_string(Parser *p, char c);
+static int end_string(Parser *p);
+static int state_escape(Parser *p, char c);
+static int state_octal(Parser *p, char c);
+static int state_hex(Parser *p, char c);
+
+static int begin_atom(Parser *p, char c);
+static int state_atom(Parser *p, char c);
+static int end_atom(Parser *p);
+
+static int state_list(Parser *p, char c);
+static int begin_list(Parser *p, char c);
+static int end_list(Parser *p);
+
+/** Print a parse error.
+ *
+ * @param in parser
+ * @param msg format followed by printf arguments
+ */
+void eprintf(Parser *in, char *msg, ...){
+    va_list args;
+    if(in->error_out){
+        va_start(args, msg);
+        IOStream_vprint(in->error_out, msg, args);
+        va_end(args);
+    }
+}
+
+/** Print a parse warning.
+ *
+ * @param in parser
+ * @param msg format followed by printf arguments
+ */
+void wprintf(Parser *in, char *msg, ...){
+    va_list args;
+    if(in->error_out){
+        va_start(args, msg);
+        IOStream_vprint(in->error_out, msg, args);
+        va_end(args);
+    }
+}
+
+/*============================================================================*/
+
+/** Record defining the message for a parse error. */
+typedef struct {
+  ParseErrorId id;
+  char *message;
+} ParseError;
+
+/** Format for printing parse error messages. */
+#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s"
+
+/** Message catalog for the parse error codes. */
+static ParseError catalog[] = {
+  { PARSE_ERR_UNSPECIFIED,            "unspecified error" },
+  { PARSE_ERR_NOMEM,                  "out of memory" },
+  { PARSE_ERR_UNEXPECTED_EOF,         "unexpected end of input" },
+  { PARSE_ERR_TOKEN_TOO_LONG,         "token too long" },
+  { PARSE_ERR_INVALID_SYNTAX,         "syntax error" },
+  { PARSE_ERR_INVALID_ESCAPE,         "invalid escape" },
+  { 0, NULL }
+};
+
+/** Number of entries in the message catalog. */
+const static int catalog_n = sizeof(catalog)/sizeof(ParseError);
+
+void ParserState_free(ParserState *z){
+    if(!z) return;
+    objfree(z->val);
+    deallocate(z);
+}
+
+int ParserState_new(ParserStateFn *fn, ParserState *parent, ParserState **val){
+    int err = 0;
+    ParserState *z;
+    z = ALLOCATE(ParserState);
+    if(z){
+        z->fn = fn;
+        z->parent = parent;
+        z->val = ONULL;
+    } else {
+        err = -ENOMEM;
+    }
+    if(!err) *val = z;
+    return err;
+}
+
+/** Free a parser.
+ * No-op if the parser is null.
+ *
+ * @param z parser 
+ */
+void Parser_free(Parser *z){
+    if(!z) return;
+    objfree(z->val);
+    z->val = ONONE;
+    deallocate(z);
+}
+
+/** Create a new parser. The error stream defaults to null.
+ */
+Parser * Parser_new(void){
+    Parser *z = ALLOCATE(Parser);
+    int err = -ENOMEM;
+  
+    if(!z) goto exit;
+    err = 0;
+    reset(z);
+  exit:
+    if(err){
+        Parser_free(z);
+        z = NULL;
+    }
+    return z;
+}
+
+/** Get the next character.
+ * Records the character read in the parser,
+ * and sets the line and character counts.
+ *
+ * @param p parser
+ * @return error flag: 0 on success, non-zero on error
+ */
+static int inputchar(Parser *p, char c){
+    int err = 0;
+    if(c=='\n'){
+        p->line_no++;
+        p->char_no = 0;
+    } else {
+        p->char_no++;
+    }
+    return err;
+}
+
+static int savechar(Parser *p, char c){
+    int err = 0;
+    if(p->buf_i >= p->buf_n){
+        err = -ENOMEM;
+        goto exit;
+    }
+    p->buf[p->buf_i] = c;
+    p->buf_i++;
+  exit:
+    return err;
+}
+
+int Parser_input_char(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        //skip;
+    } else {
+        inputchar(p, c);
+    }
+    if(!p->state){
+        err = begin_start(p, c);
+        if(err) goto exit;
+    }
+    err = p->state->fn(p, c);
+  exit:
+    return err;
+}
+
+int Parser_input_eof(Parser *p){
+    int err = 0;
+    p->eof = 1;
+    err = Parser_input_char(p, IOSTREAM_EOF);
+    return err;
+}
+
+int Parser_input(Parser *p, char *buf, int buf_n){
+    int err = 0;
+    int i = 0;
+    if(buf_n <= 0){
+        err = Parser_input_eof(p);
+        goto exit;
+    }
+    for(i = 0; i<buf_n; i++){
+        err = Parser_input_char(p, buf[i]);
+        if(err) goto exit;
+    }
+  exit:
+    err = (err < 0 ? err : buf_n);
+    return err;
+}
+
+int Parser_push(Parser *p, ParserStateFn *fn){
+    int err = 0;
+    err = ParserState_new(fn, p->state, &p->state);
+    return err;
+}
+        
+int Parser_pop(Parser *p){
+    int err = 0;
+    ParserState *s = p->state;
+    p->state = s->parent;
+    ParserState_free(s);
+    return err;
+}
+
+int Parser_return(Parser *p){
+    int err = 0;
+    Sxpr val = ONONE;
+    if(!p->state){
+        err = -EINVAL;
+        goto exit;
+    }
+    val = p->state->val;
+    p->state->val = ONONE;
+    err = Parser_pop(p);
+    if(err) goto exit;
+    if(p->state){
+        err = cons_push(&p->state->val, val);
+    } else {
+        val = nrev(val);
+        p->val = val;
+    }
+  exit:
+    if(err){
+        objfree(val);
+    }
+    return err;
+}
+
+/** Determine if a character is a separator.
+ *
+ * @param p parser
+ * @param c character to test
+ * @return 1 if a separator, 0 otherwise
+ */
+static int is_separator(Parser *p, char c){
+    return in_sep_class(c);
+}
+
+/** Return the current token.
+ * The return value points at the internal buffer, so
+ * it must not be modified (or freed). Use copy_token() if you need a copy.
+ *
+ * @param p parser
+ * @return token
+ */
+char *peek_token(Parser *p){
+    return p->buf;
+}
+
+/** Return a copy of the current token.
+ * The returned value should be freed when finished with.
+ *
+ * @param p parser
+ * @return copy of token
+ */
+char *copy_token(Parser *p){
+    return strdup(peek_token(p));
+}
+
+static int do_intern(Parser *p){
+    int err = 0;
+    Sxpr obj = intern(peek_token(p));
+    if(NOMEMP(obj)){
+        err = -ENOMEM;
+    } else {
+        p->state->val = obj;
+    }
+    return err;
+}
+
+static int do_string(Parser *p){
+    int err = 0;
+    Sxpr obj;
+    obj = string_new(peek_token(p));
+    if(NOMEMP(obj)){
+        err = -ENOMEM;
+    } else {
+        p->state->val = obj;
+    }
+    return err;
+}
+
+void newtoken(Parser *p){
+    memset(p->buf, 0, p->buf_n);
+    p->buf_i = 0;
+    p->tok_begin_line = p->line_no;
+    p->tok_begin_char = p->char_no;
+}
+
+int get_escape(char c, char *d){
+    int err = 0;
+    switch(c){
+    case 'a':            *d = '\a'; break;
+    case 'b':            *d = '\b'; break;
+    case 'f':            *d = '\f'; break;
+    case 'n':            *d = '\n'; break;
+    case 'r':            *d = '\r'; break;
+    case 't':            *d = '\t'; break;
+    case 'v':            *d = '\v'; break;
+    case c_escape:       *d = c_escape; break;
+    case c_single_quote: *d = c_single_quote; break;
+    case c_double_quote: *d = c_double_quote; break;
+    default:
+        err = -EINVAL;
+    }
+    return err;
+}
+
+
+int begin_start(Parser *p, char c){
+    return Parser_push(p, state_start);
+}
+
+int state_start(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        err = end_start(p);
+    } else if(in_space_class(c)){
+        //skip
+    } else if(in_comment_class(c)){
+        begin_comment(p, c);
+    } else if(c == c_list_open){
+        begin_list(p, c);
+    } else if(c == c_list_close){
+        parse_error(p);
+        err = -EINVAL;
+    } else if(in_string_quote_class(c)){
+        begin_string(p, c);
+    } else if(in_printable_class(c)){
+        begin_atom(p, c);
+    } else if(c == 0x04){
+        //ctrl-D, EOT: end-of-text.
+        Parser_input_eof(p);
+    } else {
+        parse_error(p);
+        err = -EINVAL;
+    }
+    return err;
+}
+
+int end_start(Parser *p){
+    int err = 0;
+    err = Parser_return(p);
+    return err;
+}
+
+int begin_comment(Parser *p, char c){
+    int err = 0;
+    err = Parser_push(p, state_comment);
+    if(err) goto exit;
+    err = inputchar(p, c);
+  exit:
+    return err;
+}
+
+int state_comment(Parser *p, char c){
+    int err = 0;
+    if(c == '\n' || at_eof(p)){
+        err = end_comment(p);
+    } else {
+        err = inputchar(p, c);
+    }
+    return err;
+}
+
+int end_comment(Parser *p){
+    return Parser_pop(p);
+}
+
+int begin_string(Parser *p, char c){
+    int err = 0;
+    err = Parser_push(p, state_string);
+    if(err) goto exit;
+    newtoken(p);
+    p->state->delim = c;
+  exit:
+    return err;
+}
+
+int state_string(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+        err = -EINVAL;
+    } else if(c == p->state->delim){
+        err = end_string(p);
+    } else if(c == '\\'){
+        err = Parser_push(p, state_escape);
+    } else {
+        err = savechar(p, c);
+    }
+    return err;
+}
+
+int end_string(Parser *p){
+    int err = 0;
+    err = do_string(p);
+    if(err) goto exit;
+    err = Parser_return(p);
+  exit:
+    return err;
+}
+
+int state_escape(Parser *p, char c){
+    int err = 0;
+    char d;
+    if(at_eof(p)){
+        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+        err = -EINVAL;
+        goto exit;
+    }
+    if(get_escape(c, &d) == 0){
+        err = savechar(p, d);
+        if(err) goto exit;
+        err = Parser_pop(p);
+    } else if(c == 'x'){
+        p->state->fn = state_hex;
+        p->state->ival = 0;
+        p->state->count = 0;
+    } else {
+        p->state->fn = state_octal;
+        p->state->ival = 0;
+        p->state->count = 0;
+        err = Parser_input_char(p, c);
+    }
+  exit:
+    return err;
+}
+
+int octaldone(Parser *p){
+    int err = 0;
+    char d = (char)(p->state->ival & 0xff);
+    err = Parser_pop(p);
+    if(err) goto exit;
+    err = Parser_input_char(p, d);
+  exit:
+    return err;
+}
+
+int octaldigit(Parser *p, char c){
+    int err = 0;
+    p->state->ival *= 8;
+    p->state->ival += c - '0'; 
+    p->state->count++;
+    if(err) goto exit;
+    if(p->state->ival < 0 || p->state->ival > 0xff){
+        parse_error(p);
+        err = -EINVAL;
+        goto exit;
+    }
+    if(p->state->count == 3){
+        err = octaldone(p);
+    }
+  exit:
+    return err;
+}
+
+int state_octal(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+        err = -EINVAL;
+        goto exit;
+    } else if('0' <= c && c <= '7'){
+        err = octaldigit(p, c);
+    } else {
+        err = octaldone(p);
+        if(err) goto exit;
+        Parser_input_char(p, c);
+    }
+  exit:
+    return err;
+}
+
+int hexdone(Parser *p){
+    int err = 0;
+    char d = (char)(p->state->ival & 0xff);
+    err = Parser_pop(p);
+    if(err) goto exit;
+    err = Parser_input_char(p, d);
+  exit:
+    return err;
+}
+    
+int hexdigit(Parser *p, char c, char d){
+    int err = 0;
+    p->state->ival *= 16;
+    p->state->ival += c - d; 
+    p->state->count++;
+    if(err) goto exit;
+    if(p->state->ival < 0 || p->state->ival > 0xff){
+        parse_error(p);
+        err = -EINVAL;
+        goto exit;
+    }
+    if(p->state->count == 2){
+        err = hexdone(p);
+    }
+  exit:
+    return err;
+}
+    
+int state_hex(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+        err = -EINVAL;
+        goto exit;
+    } else if('0' <= c && c <= '9'){
+        err = hexdigit(p, c, '0');
+    } else if('A' <= c && c <= 'F'){
+        err = hexdigit(p, c, 'A');
+    } else if('a' <= c && c <= 'f'){
+        err = hexdigit(p, c, 'a');
+    } else if(p->state->count){
+        err =hexdone(p);
+        if(err) goto exit;
+        Parser_input_char(p, c);
+    }
+  exit:
+    return err;
+}
+
+int begin_atom(Parser *p, char c){
+    int err = 0;
+    err = Parser_push(p, state_atom);
+    if(err) goto exit;
+    newtoken(p);
+    err = savechar(p, c);
+  exit:
+    return err;
+}
+
+int state_atom(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        err = end_atom(p);
+    } else if(is_separator(p, c) ||
+              in_space_class(c) ||
+              in_comment_class(c)){
+        err = end_atom(p);
+        if(err) goto exit;
+        err = Parser_input_char(p, c);
+    } else {
+        err = savechar(p, c);
+    }
+  exit:
+    return err;
+}
+
+int end_atom(Parser *p){
+    int err = 0;
+    err = do_intern(p);
+    if(err) goto exit;
+    err = Parser_return(p);
+  exit:
+    return err;
+}
+
+int state_list(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+        err = -EINVAL;
+    } else if(c == c_list_close){
+        p->state->val = nrev(p->state->val);
+        err = end_list(p);
+    } else {
+        err = state_start(p, c);
+    }
+    return err;
+    
+}
+
+int begin_list(Parser *p, char c){
+    return Parser_push(p, state_list);
+}
+
+int end_list(Parser *p){
+    return Parser_return(p);
+}
+
+/** Reset the fields of a parser to initial values.
+ *
+ * @param z parser
+ */
+static void reset(Parser *z){
+  IOStream *error_out = z->error_out;
+  int flags = z->flags;
+  zero(z, sizeof(Parser));
+  z->buf_n = sizeof(z->buf) - 1;
+  z->buf_i = 0;
+  z->line_no = 1;
+  z->char_no = 0;
+  z->error_out = error_out;
+  z->flags = flags;
+}
+
+/** Set the parser error stream.
+ * Parse errors are reported on the the error stream if it is non-null.
+ * 
+ * @param z parser
+ * @param error_out error stream
+ */
+void set_error_stream(Parser *z, IOStream *error_out){
+  if(z){
+    z->error_out = error_out;
+  }
+}
+
+/** Get the parser error message for an error code.
+ *
+ * @param id error code
+ * @return error message (empty string if the code is unknown)
+ */
+static char *get_message(ParseErrorId id){
+  int i;
+  for(i=0; i<catalog_n; i++){
+    if(id == catalog[i].id){
+      return catalog[i].message;
+    }
+  }
+  return "";
+}
+
+/** Get the line number.
+ *
+ * @param in parser
+ */
+int get_line(Parser *in){
+  return in->line_no;
+}
+
+/** Get the column number.
+ *
+ * @param in parser
+ */
+int get_column(Parser *in){
+  return in->char_no;
+}
+
+/** Get the line number the current token started on.
+ *
+ * @param in parser
+ */
+int get_tok_line(Parser *in){
+  return in->tok_begin_line;
+}
+
+/** Get the column number the current token started on.
+ *
+ * @param in parser
+ */
+int get_tok_column(Parser *in){
+  return in->tok_begin_char;
+}
+
+/** Report a parse error.
+ * Does nothing if the error stream is null or there is no error.
+ *
+ * @param in parser
+ */
+static void report_error(Parser *in){
+  if(in->error_out && in->err){
+    char *msg = get_message(in->err);
+    char *tok = peek_token(in);
+    IOStream_print(in->error_out, PARSE_ERR_FMT,
+                  get_tok_line(in), get_tok_column(in), msg);
+    if(tok && tok[0]){
+        IOStream_print(in->error_out, " '%s'", tok);
+    }
+    IOStream_print(in->error_out, "\n");
+  }
+}
+
+/** Get the error message for the current parse error code.
+ * Does nothing if there is no error.
+ *
+ * @param in parser
+ * @param buf where to place the message
+ * @param n maximum number of characters to place in buf
+ * @return current error code (zero for no error)
+ */
+int parse_error_message(Parser *in, char *buf, int n){
+    if(in->err){
+        char *msg = get_message(in->err);
+        snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg);
+    }
+    return in->err;
+}
+
+/** Flag an unspecified parse error. All subsequent reads will fail.
+ *
+ * @param in parser
+ */
+void parse_error(Parser *in){
+    parse_error_id(in, PARSE_ERR_INVALID_SYNTAX);
+}
+
+/** Flag a parse error. All subsequent reads will fail.
+ * Does not change the parser error code if it is already set.
+ *
+ * @param in parser
+ * @param id error code
+ */
+void parse_error_id(Parser *in, ParseErrorId id){
+    if(!in->err){
+        in->err = id;
+        report_error(in);
+    }
+}
+
+/** Test if the parser's error flag is set.
+ *
+ * @param in parser
+ * @return 1 if set, 0 otherwise
+ */
+int has_error(Parser *in){
+    return (in->err > 0);
+}
+
+/** Test if the parser is at end of input.
+ *
+ * @param in parser
+ * @return 1 if at EOF, 0 otherwise
+ */
+int at_eof(Parser *p){
+    return p->eof;
+}
+
+#ifdef SXPR_PARSER_MAIN
+/* Stuff for standalone testing. */
+
+#include "file_stream.h"
+#include "string_stream.h"
+
+int stringof(Sxpr exp, char **s){
+    int err = 0;
+    if(ATOMP(exp)){
+        *s = atom_name(exp);
+    } else if(STRINGP(exp)){
+        *s = string_string(exp);
+    } else {
+        err = -EINVAL;
+        *s = NULL;
+    }
+    return err;
+}
+
+int child_string(Sxpr exp, Sxpr key, char **s){
+    int err = 0;
+    Sxpr val = sxpr_child_value(exp, key, ONONE);
+    err = stringof(val, s);
+    return err;
+}
+
+int intof(Sxpr exp, int *v){
+    int err = 0;
+    char *s;
+    unsigned long l;
+    if(INTP(exp)){
+        *v = OBJ_INT(exp);
+    } else {
+        err = stringof(exp, &s);
+        if(err) goto exit;
+        err = convert_atoul(s, &l);
+        *v = (int)l;
+    }
+ exit:
+    return err;
+}
+
+int child_int(Sxpr exp, Sxpr key, int *v){
+    int err = 0;
+    Sxpr val = sxpr_child_value(exp, key, ONONE);
+    err = intof(val, v);
+    return err;
+}
+
+int eval_vnet(Sxpr exp){
+    int err = 0;
+    Sxpr oid = intern("id");
+    int id;
+    err = child_int(exp, oid, &id);
+    if(err) goto exit;
+    dprintf("> vnet id=%d\n", id);
+ exit:
+    dprintf("< err=%d\n", err);
+    return err;
+}
+
+int eval_connect(Sxpr exp){
+    int err = 0;
+    Sxpr ovif = intern("vif");
+    Sxpr ovnet = intern("vnet");
+    char *vif;
+    int vnet;
+
+    err = child_string(exp, ovif, &vif);
+    if(err) goto exit;
+    err = child_int(exp, ovnet, &vnet);
+    if(err) goto exit;
+    dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
+ exit:
+    dprintf("< err=%d\n", err);
+    return err;
+}
+
+int eval(Sxpr exp){
+    int err = 0;
+    Sxpr oconnect = intern("connect");
+    Sxpr ovnet = intern("vnet");
+    
+    if(sxpr_elementp(exp, ovnet)){
+        err = eval_vnet(exp);
+    } else if(sxpr_elementp(exp, oconnect)){
+        err = eval_connect(exp);
+    } else {
+        err = -EINVAL;
+    }
+    return err;
+}
+
+/** Main program for testing.
+ * Parses input and prints it.
+ *
+ * @param argc number of arguments
+ * @param argv arguments
+ * @return error code
+ */
+int main(int argc, char *argv[]){
+    Parser *pin;
+    int err = 0;
+    char buf[1024];
+    int k;
+    Sxpr obj, l, x;
+
+    pin = Parser_new();
+    set_error_stream(pin, iostdout);
+    dprintf("> parse...\n");
+    while(1){
+        k = fread(buf, 1, 1024, stdin);
+        err = Parser_input(pin, buf, k);
+        dprintf("> Parser_input=%d\n", err);
+        if(k <= 0) break;
+    }
+    obj = pin->val;
+    for(l = obj ; CONSP(l); l = CDR(l)){
+        x = CAR(l);
+        objprint(iostdout, x, 0); printf("\n");
+        eval(x);
+    }
+    dprintf("> err=%d\n", err);
+    return 0;
+}
+#endif
diff --git a/tools/libxutil/sxpr_parser.h b/tools/libxutil/sxpr_parser.h
new file mode 100644 (file)
index 0000000..7296312
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or  (at your option) any later version. This library is 
+ * distributed in the  hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef _XEN_LIB_SXPR_PARSER_H_
+#define _XEN_LIB_SXPR_PARSER_H_
+
+#include "sxpr.h"
+#include "iostream.h"
+
+/** @file
+ * Sxpr parsing definitions.
+ */
+
+/** Size of a parser input buffer.
+ * Tokens read must fit into this size (including trailing null).
+ */
+#define PARSER_BUF_SIZE 1024
+
+struct Parser;
+typedef int ParserStateFn(struct Parser *, char c);
+
+typedef struct ParserState {
+    struct ParserState *parent;
+    Sxpr val;
+    int ival;
+    int count;
+    char delim;
+    ParserStateFn *fn;
+} ParserState;
+
+/** Structure representing an input source for the parser.
+ * Can read from any IOStream implementation.
+ */
+typedef struct Parser {
+    Sxpr val;
+    /** Error reporting stream (null for no reports). */
+    IOStream *error_out;
+    int eof;
+    /** Error flag. Non-zero if there has been a read error. */
+    int err;
+    /** Line number on input (from 1). */
+    int line_no;
+    /** Column number of input (reset on new line). */
+    int char_no;
+    /** Lookahead character. */
+    char c;
+    /** Buffer for reading tokens. */
+    char buf[PARSER_BUF_SIZE];
+    /** Size of token buffer. */
+    int buf_n;
+    int buf_i;
+    /** Line the last token started on. */
+    int tok_begin_line;
+    /** Character number the last token started on. */
+    int tok_begin_char;
+    /** Parsing flags. */
+    int flags;
+    ParserState *state;
+} Parser;
+
+/** Parser error codes. */
+typedef enum {
+    PARSE_ERR_NONE=0,
+    PARSE_ERR_UNSPECIFIED,
+    PARSE_ERR_NOMEM,
+    PARSE_ERR_UNEXPECTED_EOF,
+    PARSE_ERR_TOKEN_TOO_LONG,
+    PARSE_ERR_INVALID_SYNTAX,
+    PARSE_ERR_INVALID_ESCAPE,
+} ParseErrorId;
+
+
+/** Parser flags. */
+//enum {
+//};
+
+/** Raise some parser flags.
+ *
+ * @param in parser
+ * @param flags flags mask
+ */
+inline static void parser_flags_raise(Parser *in, int flags){
+    in->flags |= flags;
+}
+
+/** Lower some parser flags.
+ *
+ * @param in parser
+ * @param flags flags mask
+ */
+inline static void parser_flags_lower(Parser *in, int flags){
+    in->flags &= ~flags;
+}
+
+/** Clear all parser flags.
+ *
+ * @param in parser
+ */
+inline static void parser_flags_clear(Parser *in){
+    in->flags = 0;
+}
+
+extern void Parser_free(Parser *z);
+extern Parser * Parser_new(void);
+extern int Parser_input(Parser *p, char *buf, int buf_n);
+extern int Parser_input_eof(Parser *p);
+
+extern int parse_error_message(Parser *in, char *buf, int n);
+extern int has_error(Parser *in);
+extern int at_eof(Parser *in);
+
+#endif /* ! _XEN_LIB_SXPR_PARSER_H_ */
diff --git a/tools/libxutil/sys_ctype.h b/tools/libxutil/sys_ctype.h
new file mode 100644 (file)
index 0000000..1dc6cf2
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _XENO_SYS_CTYPE_H_
+#define _XENO_SYS_CTYPE_H_
+/** @file
+ ** Replacement for ctype include that can be used
+ * from user or kernel code.
+ */
+#ifdef __KERNEL__
+#  include <linux/ctype.h>
+#else
+#  include <ctype.h>
+#endif
+#endif /* ! _XENO_SYS_CTYPE_H_ */
diff --git a/tools/libxutil/sys_net.c b/tools/libxutil/sys_net.c
new file mode 100644 (file)
index 0000000..0e7ac5d
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or  (at your option) any later version. This library is 
+ * distributed in the  hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include "sys_net.h"
+#include "sys_string.h"
+
+/** @file
+ * All network data are kept in network order and only converted to
+ * host order for display. Network data includes IP addresses, port numbers and
+ * network masks.
+ */
+
+/** Maximum value for a port. */
+#define PORT_MAX 0xffff
+
+/** Convert a number of bits to a network mask
+ * for IP addresses. The number of bits must
+ * be in the range 1-31.
+ *
+ * @param n number of bits to set in the mask
+ * @return value with n high bits set (in network order)
+ */
+unsigned long bits_to_mask(int n){
+    unsigned long mask = (n ? (1 << 31) : 0);
+    int i;
+    for(i=1; i<n; i++){
+        mask |= (mask >> 1);
+    }
+    return htonl(mask);
+}
+
+/** Convert a network mask to a number of bits.
+ *
+ * @param mask network mask in network order
+ * @return number of bits in mask
+ */
+int mask_to_bits(unsigned long mask){
+    // Start with n set to the number of bits in the mask. Then reduce n by
+    // the number of low zero bits in the mask.
+    int n = 32;
+    for(mask = ntohl(mask);
+        (mask & 1)==0 && n>0;
+        mask >>= 1){
+        n--;
+    }
+    return n;
+}
+
+/** Get the index of the first occurrence of a character in a string.
+ * Stops at end of string or after n characters.
+ *
+ * @param s input string
+ * @param n maximum number of charactes to search
+ * @param c character to look for
+ * @return index of first occurrence, -1 if not found
+ */
+inline static int indexof(const char *s, int n, char c){
+    int i;
+    for(i=0; i<n && *s; i++, s++){
+        if(*s == c) return i;
+    }
+    return -1;
+}
+
+/** Convert an IPv4 address in dot notation into an unsigned long (in network order).
+ *
+ * @param s input string
+ * @param address where to put the address
+ * @return 0 on success, -1 on error
+ */
+int get_inet_addr(const char *s, unsigned long *address){
+    // Number of bits in a byte.
+    const int BYTE_BITS = 8;
+    // Number of bytes in a word.
+    const int WORD_BYTES = 4;
+    // Max value for a component of an address.
+    const int ADDR_MAX  = 255;
+    // Separator for components of an address.
+    const char dot = '.';
+
+    int n;
+    unsigned long addr = 0;
+    unsigned long v;
+    int i;
+    int err = -1;
+    // Bit shift for the current byte.
+    int shift = BYTE_BITS * (WORD_BYTES - 1);
+    char buf[64];
+
+    n = strlen(s);
+    if(n >= sizeof(buf)){
+        goto exit;
+    }
+    for(i=0; i < WORD_BYTES; i++){
+        int idx = indexof(s, n, dot);
+        idx = (idx < 0 ? strlen(s) : idx);
+        strncpy(buf, s, idx); buf[idx]='\0';
+        if(convert_atoul(buf, &v)){
+            goto exit;
+        }
+        if(v < 0 || v > ADDR_MAX){
+            goto exit;
+        }
+        addr |= (v << shift);
+        if(idx == n) break;
+        shift -= BYTE_BITS;
+        s += idx+1;
+    }
+    err = 0;
+  exit:
+    addr = htonl(addr);
+    *address = (err ? 0 : addr);
+    return err;
+}
+
+#ifdef __KERNEL__
+/** Convert an address in network order to IPv4 dot notation.
+ * The return value is a static buffer which is overwritten on each call.
+ *
+ * @param inaddr address (in network order)
+ * @return address in dot notation
+ */
+char *inet_ntoa(struct in_addr inaddr){
+    static char address[16] = {};
+    uint32_t addr = ntohl(inaddr.s_addr);
+    snprintf(address, sizeof(address), "%d.%d.%d.%d",
+            (unsigned)((addr >> 24) & 0xff),
+            (unsigned)((addr >> 16) & 0xff),
+            (unsigned)((addr >>  8) & 0xff),
+            (unsigned)((addr      ) & 0xff));
+    return address;
+}
+
+
+/** Convert a string in IPv4 dot notation to an int in network order.
+ *
+ * @param address address in dot notation
+ * @param inp result of conversion (in network order)
+ * @return 0 on success, error code on error
+ */
+int inet_aton(const char *address, struct in_addr *inp){
+    int err = 0; 
+    unsigned long addr;
+    
+    err = get_inet_addr(address, &addr);
+    if(err) goto exit;
+    inp->s_addr = addr;
+  exit:
+    return err;
+}
+#endif
+
+/** Convert a hostname or IPv4 address string to an address in network order.
+ *
+ * @param name input hostname or address string
+ * @param address where to put the address
+ * @return 1 if address found OK, 0 otherwise
+ */
+int get_host_address(const char *name, unsigned long *address){
+#ifdef __KERNEL__
+    return get_inet_addr(name, address) == 0;
+#else
+    struct hostent *host = gethostbyname(name);
+    if(!host){
+        return 0;
+    }
+    *address = ((struct in_addr *)(host->h_addr))->s_addr;
+    return 1;
+#endif
+}
+
+/** Convert a service name to a port (in network order).
+ *
+ * @param name service name
+ * @param port where to put the port
+ * @return 1 if service port found OK, 0 otherwise
+ */
+int get_service_port(const char *name, unsigned long *port){
+#ifdef __KERNEL__
+    return 0;
+#else
+    struct servent *service;
+    service = getservbyname(name, 0);
+    if(!service){
+        return 0;
+    }
+    *port = service->s_port;
+    return 1;
+#endif
+}
+
+/** Convert a port number (in network order) to a service name.
+ *
+ * @param port the port number
+ * @return service name if found OK, 0 otherwise
+ */
+char *get_port_service(unsigned long port){
+#ifdef __KERNEL__
+    return 0;
+#else
+    struct servent *service = getservbyport(port, 0);
+    return (service ? service->s_name : 0);
+#endif
+}
+
+/** Convert a decimal integer or service name to a port (in network order).
+ *
+ * @param s input to convert
+ * @param port where to put the port
+ * @return 1 if port found OK, 0 otherwise
+ */
+int convert_service_to_port(const char *s, unsigned long *port){
+    int ok = 0;
+    unsigned long value;
+    if(convert_atoul(s, &value)){
+        ok = get_service_port(s, &value);
+    } else {
+        ok = (0 <= value) && (value <= PORT_MAX);
+        value = htons((unsigned short)value);
+    }
+    *port = (ok ? value : 0);
+    return ok;
+}
+
+#define MAC_ELEMENT_N  6 // Number of elements in a MAC address.
+#define MAC_DIGIT_N    2 // Number of digits in an element in a MAC address.
+#define MAC_LENGTH    17 //((MAC_ELEMENT_N * MAC_DIGIT_N) + MAC_ELEMENT_N - 1)
+
+/** Convert a mac address from a string of the form
+ * XX:XX:XX:XX:XX:XX to numerical form (an array of 6 unsigned chars).
+ * Each X denotes a hex digit: 0..9, a..f, A..F.
+ * Also supports using '-' as the separator instead of ':'.
+ *
+ * @param mac_in string to convert
+ * @param mac destination for the value
+ * @return 0 on success, -1 on error
+ */
+int mac_aton(const char *mac_in, unsigned char *mac){
+    int err = 0;
+    int i, j;
+    const char *p;
+    char sep = 0;
+    unsigned char d;
+    if(!mac_in || strlen(mac_in) != MAC_LENGTH){
+        err = -1;
+        goto exit;
+    }
+    for(i = 0, p = mac_in; i < MAC_ELEMENT_N; i++){
+        d = 0;
+        if(i){
+            if(!sep){
+                if(*p == ':' || *p == '-') sep = *p;
+            }
+            if(sep && *p == sep){
+                p++;
+            } else {
+                err = -1;
+                goto exit;
+            }
+        }
+        for(j = 0; j < MAC_DIGIT_N; j++, p++){
+            if(j) d <<= 4;
+            if(*p >= '0' && *p <= '9'){
+                d += (*p - '0');
+            } else if(*p >= 'A' && *p <= 'F'){
+                d += (*p - 'A') + 10;
+            } else if(*p >= 'a' && *p <= 'f'){
+                d += (*p - 'a') + 10;
+            } else {
+                err = -1;
+                goto exit;
+            }
+        }
+        mac[i] = d;
+    }
+  exit:
+    return err;
+}
+
+/** Convert a MAC address from numerical form to a string.
+ *
+ * @param mac address to convert
+ * @return static string value
+ */
+char *mac_ntoa(const unsigned char *mac){
+    static char buf[MAC_LENGTH + 1];
+    int buf_n = sizeof(buf);
+
+    memset(buf, buf_n, 0);
+    snprintf(buf, buf_n, "%02x:%02x:%02x:%02x:%02x:%02x",
+             mac[0], mac[1], mac[2],
+             mac[3], mac[4], mac[5]);
+    buf[buf_n - 1] = '\0';
+    return buf;
+}
diff --git a/tools/libxutil/sys_net.h b/tools/libxutil/sys_net.h
new file mode 100644 (file)
index 0000000..da6c1e8
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _XEN_LIB_SYS_NET_H_
+#define _XEN_LIB_SYS_NET_H_
+/** @file
+ *
+ * Replacement for standard network includes.
+ * Works in user or kernel code.
+ */
+
+extern int get_inet_addr(const char *s, unsigned long *address);
+extern unsigned long bits_to_mask(int n);
+extern int mask_to_bits(unsigned long mask);
+extern int get_host_address(const char *name, unsigned long *address);
+extern int get_service_port(const char *name, unsigned long *port);
+extern char *get_port_service(unsigned long port);
+extern int convert_service_to_port(const char *s, unsigned long *port);
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h> 
+
+#ifndef htonl
+#define htonl(x) __constant_htonl(x)
+#endif
+
+#ifndef ntohl
+#define ntohl(x) __constant_ntohl(x)
+#endif
+
+#ifndef htons
+#define htons(x) __constant_htons(x)
+#endif
+
+#ifndef ntohs
+#define ntohs(x) __constant_ntohs(x)
+#endif
+
+#include <linux/in.h>
+extern char *inet_ntoa(struct in_addr inaddr);
+extern int inet_aton(const char *address, struct in_addr *inp);
+
+#else
+
+#include <limits.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#endif
+
+extern char *mac_ntoa(const unsigned char *macaddr);
+extern int mac_aton(const char *addr, unsigned char *macaddr);
+
+#endif /* !_SP_SYS_NET_H_ */
+
+
+
diff --git a/tools/libxutil/sys_string.c b/tools/libxutil/sys_string.c
new file mode 100644 (file)
index 0000000..13a90df
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef __KERNEL__
+#  include <linux/config.h>
+#  include <linux/module.h>
+#  include <linux/kernel.h>
+#  include <linux/errno.h>
+#else
+#  include <errno.h>
+#endif
+
+#include "allocate.h"
+#include "sys_string.h"
+
+/** Set the base to use for converting a string to a number.  Base is
+ * hex if starts with 0x, otherwise decimal.
+ *
+ * @param s input string
+ * @param base where to put the base
+ * @return rest of s to parse as a number
+ */
+inline static const char * convert_set_base(const char *s, int *base){
+    *base = 10;
+    if(s){
+        if(*s=='0'){
+            s++;
+            if(*s=='x' || *s=='X'){
+                *base = 16;
+                s++;
+            }
+        }
+    }
+    return s;
+}
+
+/** Get the numerical value of a digit in the given base.
+ *
+ * @param c digit character
+ * @param base to use
+ * @return numerical value of digit in range 0..base-1 or
+ * -1 if not in range for the base
+ */
+inline static int convert_get_digit(char c, int base){
+    int d;
+
+    if('0'<=c  && c<='9'){
+        d = c - '0';
+    } else if('a'<=c && c<='f'){
+        d = c - 'a' + 10;
+    } else if('A'<=c && c<='F'){
+        d = c - 'A' + 10;
+    } else {
+        d = -1;
+    }
+    return (d < base ? d : -1);
+}
+
+/** Convert a string to an unsigned long by parsing it as a number.
+ * Will accept hex or decimal in usual C syntax.
+ *
+ * @param str input string
+ * @param val where to put the result
+ * @return 0 if converted OK, negative otherwise
+ */
+int convert_atoul(const char *str, unsigned long *val){
+    int err = 0;
+    unsigned long v = 0;
+    int base;
+    const char *s = str;
+
+    if(!s) {
+        err = -EINVAL;
+        goto exit;
+    }
+    s = convert_set_base(s, &base);
+    for( ; !err && *s; s++){
+        int digit = convert_get_digit(*s, base);
+        if(digit<0){
+            err = -EINVAL;
+            goto exit;
+        }
+        v *= base;
+        v += digit;
+    } 
+  exit:
+    *val = (err ? 0 : v);
+    return err;
+}
+
+/** Combine a directory path with a relative path to produce
+ * a new path.
+ *
+ * @param s directory path
+ * @param t relative path
+ * @return new combined path s/t
+ */
+int path_concat(char *s, char *t, char **val){
+    int err = 0;
+    int sn, tn, vn;
+    char *v;
+    sn = strlen(s);
+    if(sn > 0 && s[sn-1] == '/'){
+        sn--;
+    }
+    tn = strlen(t);
+    if(tn > 0 && t[0] == '/'){
+        tn--;
+    }
+    vn = sn+tn+1;
+    v = (char*)allocate(vn+1);
+    if(!v){
+        err = -ENOMEM;
+        goto exit;
+    }
+    strncpy(v, s, sn);
+    v[sn] = '/';
+    strncpy(v+sn+1, t, tn);
+    v[vn] = '\0';
+  exit:
+    *val = (err ? NULL : v);
+    return err;    
+}
diff --git a/tools/libxutil/sys_string.h b/tools/libxutil/sys_string.h
new file mode 100644 (file)
index 0000000..f39935f
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _XEN_LIB_SYS_STRING_H_
+#define _XEN_LIB_SYS_STRING_H_
+/** @file
+ * Replacement for standard string includes.
+ * Works in user or kernel code.
+ */
+/*============================================================================*/
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <stdarg.h>
+#include "allocate.h"
+
+#if 0
+static inline int tolower(int c){
+    return (c>='A' && c<='Z' ? (c-'A')+'a' : c);
+}
+#endif
+
+static inline int isalpha(int c){
+    return (c>='A' && c<='Z') || (c>='a' && c<='z');
+}
+
+static inline int isdigit(int c){
+   return (c>='0' && c<='9');
+}
+
+#if 0
+static inline int strcasecmp(const char *s1, const char *s2){
+       int c1, c2;
+
+       do {
+               c1 = tolower(*s1++);
+               c2 = tolower(*s2++);
+       } while (c1 && c1 == c2);
+       return c1 - c2;
+}
+#endif
+
+static inline char * strdup(const char *s){
+    int n = (s ? 1+strlen(s) : 0);
+    char *copy = (n ? allocate(n) : NULL);
+    if(copy){
+        strcpy(copy, s);
+    }
+    return copy;
+}
+
+/*============================================================================*/
+#else
+#include <string.h>
+#include <stdio.h>
+
+#ifndef _GNU_SOURCE
+static inline size_t strnlen(const char *s, size_t n){
+    int k = 0;
+    if(s){
+       for(k=0; *s && k<n; s++, k++){}
+    }
+    return k;
+}
+#endif
+
+#endif
+/*============================================================================*/
+
+extern int convert_atoul(const char *s, unsigned long *v);
+extern int path_concat(char *s, char *t, char **val);
+
+#endif /* !_XEN_LIB_SYS_STRING_H_ */
diff --git a/tools/libxutil/xdr.c b/tools/libxutil/xdr.c
new file mode 100644 (file)
index 0000000..dfb91f2
--- /dev/null
@@ -0,0 +1,246 @@
+/* $Id: xdr.c,v 1.3 2003/09/29 13:40:00 mjw Exp $ */
+#include "xdr.h"
+#include <errno.h>
+/** @file
+ * XDR packer/unpacker for elements.
+ *
+ * string -> [T_STRING] [len:u32] <len bytes>
+ * atom   -> [T_ATOM]   [len:u32] <len bytes>
+ * uint   -> [T_UINT]   [value]
+ * cons   -> [T_CONS]   <car> <cdr>
+ * null   -> [T_NULL]
+ * none   -> [T_NONE]
+ * bool   -> [T_BOOL]   { 0:u8 | 1:u8 }
+ *
+ * types packed as u16.
+ *
+ * So (a b c) -> [T_CONS] a [T_CONS] b [T_CONS] c [T_NULL]
+ *    ()      -> [T_NULL]
+ */
+
+int pack_bool(IOStream *io, int x){
+    int err=0;
+    err = IOStream_print(io, "%c", 0xff & x);
+    if(err > 0) err = 0;
+    return err;
+}
+
+int unpack_bool(IOStream *io, int *x){
+    int err = 0;
+    int c;
+    c = IOStream_getc(io);
+    *x = (c < 0 ? 0 : c);
+    err = IOStream_error(io);
+    if(c < 0 && !err) err = -EIO;
+    return err;
+}
+
+int pack_ushort(IOStream *io, unsigned short x){
+    int err=0;
+    err = IOStream_print(io, "%c%c",
+                         0xff & (x >>  8),
+                         0xff & (x      ));
+    if(err > 0) err = 0;
+    return err;
+}
+
+int unpack_ushort(IOStream *io, unsigned short *x){
+    int err = 0;
+    int i, c = 0;
+    *x = 0;
+    for(i = 0; i< 2; i++){
+        c = IOStream_getc(io);
+        if(c < 0) break;
+        *x <<= 8;
+        *x |= (0xff & c);
+    }
+    err = IOStream_error(io);
+    if(c < 0 && !err) err = -EIO;
+    return err;
+}
+
+int pack_uint(IOStream *io, unsigned int x){
+    int err=0;
+    err = IOStream_print(io, "%c%c%c%c",
+                         0xff & (x >> 24),
+                         0xff & (x >> 16),
+                         0xff & (x >>  8),
+                         0xff & (x      ));
+    if(err > 0) err = 0;
+    return err;
+}
+
+int unpack_uint(IOStream *io, unsigned int *x){
+    int err = 0;
+    int i, c = 0;
+    *x = 0;
+    for(i = 0; i< 4; i++){
+        c = IOStream_getc(io);
+        if(c < 0) break;
+        *x <<= 8;
+        *x |= (0xff & c);
+    }
+    err = IOStream_error(io);
+    if(c < 0 && !err) err = -EIO;
+    return err;
+}
+
+int pack_string(IOStream *io, Sxpr x){
+    int err = 0;
+    int n = string_length(x);
+    char *s = string_string(x);
+    int i;
+    err = pack_uint(io, n);
+    if(err) goto exit;
+    for(i = 0; i < n; i++){
+        err = IOStream_print(io, "%c", s[i]);
+        if(err < 0) break;
+    }
+    if(err > 0) err = 0;
+  exit:
+    return err;
+}
+
+int unpack_string(IOStream *io, Sxpr *x){
+    int err;
+    unsigned int n;
+    int i, c = 0;
+    char *s;
+    Sxpr val = ONONE;
+    
+    err = unpack_uint(io, &n);
+    if(err) goto exit;
+    val = halloc(n+1, T_STRING);
+    if(NOMEMP(val)){
+        err = -ENOMEM;
+        goto exit;
+    }
+    s = string_string(val);
+    for(i=0; i<n; i++){
+        c = IOStream_getc(io);
+        if(c < 0) break;
+        s[i] = (char)c;
+    }
+    s[n] = '\0';
+  exit:
+    err = IOStream_error(io);
+    if(c < 0 && !err) err = -EIO;
+    if(err){
+        objfree(val);
+        val = ONONE;
+    }
+    *x = val;
+    return err;
+}
+
+int pack_cons(IOStream *io, Sxpr x){
+    int err = 0;
+    err = pack_sxpr(io, CAR(x));
+    if(err) goto exit;
+    err = pack_sxpr(io, CDR(x));
+  exit:
+    return err;
+}
+
+int unpack_cons(IOStream *io, Sxpr *x){
+    int err = 0;
+    Sxpr u = ONONE, v = ONONE, val = ONONE;
+    err = unpack_sxpr(io, &u);
+    if(err) goto exit;
+    err = unpack_sxpr(io, &v);
+    if(err) goto exit;
+    val = cons_new(u, v);
+    if(NOMEMP(val)){
+        err = -ENOMEM;
+    }
+  exit:
+    if(err){
+        objfree(u);
+        objfree(v);
+        val = ONONE;
+    }        
+    *x = val;
+    return err;
+}
+
+int pack_sxpr(IOStream *io, Sxpr x){
+    int err = 0;
+    unsigned short type = get_type(x);
+    err = pack_ushort(io, type);
+    if(err) goto exit;
+    switch(type){
+    case T_NULL:
+        break;
+    case T_NONE:
+        break;
+        break;
+    case T_BOOL:
+        err = pack_bool(io, get_ul(x));
+        break;
+    case T_CONS:
+        err = pack_cons(io, x);
+        break;
+    case T_ATOM:
+        err = pack_string(io, OBJ_ATOM(x)->name);
+        break;
+    case T_STRING:
+        err = pack_string(io, x);
+        break;
+    case T_UINT:
+        err = pack_uint(io, get_ul(x));
+        break;
+    default:
+        err = -EINVAL;
+        IOStream_print(iostderr, "%s> invalid type %d\n", __FUNCTION__, type);
+        break;
+    }
+  exit:
+    return err;
+}
+
+int unpack_sxpr(IOStream *io, Sxpr *x){
+    int err = 0;
+    unsigned short type;
+    unsigned int u;
+    Sxpr val = ONONE, y;
+
+    err = unpack_ushort(io, &type);
+    if(err) goto exit;
+    switch(type){
+    case T_NULL:
+        val = ONULL;
+        break;
+    case T_NONE:
+        val = ONONE;
+        break;
+    case T_CONS:
+        err = unpack_cons(io, &val);
+        break;
+    case T_BOOL:
+        err = unpack_bool(io, &u);
+        if(err) goto exit;
+        val = (u ? OTRUE : OFALSE);
+        break;
+    case T_ATOM:
+        err = unpack_string(io, &y);
+        if(err) goto exit;
+        val = intern(string_string(y));
+        objfree(y);
+        break;
+    case T_STRING:
+        err = unpack_string(io, &val);
+        break;
+    case T_UINT:
+        err = unpack_uint(io, &u);
+        if(err) goto exit;
+        val = OBJI(type, u);
+        break;
+    default:
+        err = -EINVAL;
+        IOStream_print(iostderr, "%s> invalid type %d\n", __FUNCTION__, type);
+        break;
+    }
+  exit:
+    *x = (err ? ONONE : val);
+    return err;
+}
diff --git a/tools/libxutil/xdr.h b/tools/libxutil/xdr.h
new file mode 100644 (file)
index 0000000..cb7d97d
--- /dev/null
@@ -0,0 +1,14 @@
+/* $Id: xdr.h,v 1.2 2003/09/29 13:40:00 mjw Exp $ */
+#ifndef _SP_XDR_H_
+#define _SP_XDR_H_
+#include "iostream.h"
+#include "sxpr.h"
+int pack_uint(IOStream *out, unsigned int x);
+int unpack_uint(IOStream *in, unsigned int *x);
+int pack_string(IOStream *out, Sxpr x);
+int unpack_string(IOStream *in, Sxpr *x);
+int pack_cons(IOStream *out, Sxpr x);
+int unpack_cons(IOStream *in, Sxpr *x);
+int pack_sxpr(IOStream *out, Sxpr x);
+int unpack_sxpr(IOStream *in, Sxpr *x);
+#endif /* _SP_XDR_H_ */
index 9df04d8ea2d1c2fe8a7594a5b471079b9a4620a0..979599736411414b71ae857193a1a0da56b2c73b 100644 (file)
@@ -1,10 +1,18 @@
 
+XEN_ROOT=../..
+include $(XEN_ROOT)/tools/Make.defs
+
 CC         = gcc
 CFLAGS     = -Wall -O3 
-EXTRA_INC  = -I../../xen/include/hypervisor-ifs
-EXTRA_INC += -I../../linux-xen-sparse/include -I../xc/lib
-EXTRA_INC += -I../xu/lib
-EXTRA_INC += -I../lib
+
+INCLUDES += -I $(XEN_HYPERVISOR_IFS)
+INCLUDES += -I $(XEN_LINUX_INCLUDE)
+INCLUDES += -I $(XEN_XC)
+INCLUDES += -I $(XEN_XU)
+INCLUDES += -I $(XEN_LIBXC)
+INCLUDES += -I $(XEN_LIBXUTIL)
+
+CFLAGS += $(INCLUDES)
 
 HDRS     = $(wildcard *.h)
 SRCS     = $(wildcard *.c)
@@ -12,7 +20,8 @@ OBJS     = $(patsubst %.c,%.o,$(SRCS))
 
 TARGETS  = xen_cpuperf
 
-INSTALL  = $(TARGETS) xencons
+INSTALL_BIN  = $(TARGETS) xencons
+INSTALL_SBIN = netfix xm xend
 
 all: $(TARGETS)
        $(MAKE) -C miniterm
@@ -20,8 +29,8 @@ all: $(TARGETS)
 install: all
        mkdir -p $(prefix)/usr/bin
        mkdir -p $(prefix)/usr/sbin
-       install -m0755 $(INSTALL) $(prefix)/usr/bin
-       install -m0755 netfix $(prefix)/usr/sbin
+       install -m0755 $(INSTALL_BIN) $(prefix)/usr/bin
+       install -m0755 $(INSTALL_SBIN) $(prefix)/usr/sbin
        $(MAKE) -C miniterm install
 
 clean:
@@ -29,4 +38,4 @@ clean:
        $(MAKE) -C miniterm clean       
 
 %: %.c $(HDRS) Makefile
-       $(CC) $(CFLAGS) $(EXTRA_INC) -o $@ $<
+       $(CC) $(CFLAGS) -o $@ $<
index def4e28a6cca7f972a7bad865d95883e4597acf6..df38e438a1868b2e78a8b95c8e522c09b79e9e04 100644 (file)
@@ -1,5 +1,6 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 #  -*- mode: python; -*-
+#============================================================================
 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
 #============================================================================
 # Move the IP address from eth0 onto the Xen bridge (nbe-br).
@@ -7,7 +8,7 @@
 #============================================================================
 
 from getopt import getopt
-from xen.xend.XendBridge import *
+from xen.util.Brctl import *
 
 short_options = 'hvqni:b:c'
 long_options  = ['help', 'verbose', 'quiet',
diff --git a/tools/misc/xend b/tools/misc/xend
new file mode 100644 (file)
index 0000000..0600649
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+#  -*- mode: python; -*-
+#============================================================================
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+#============================================================================
+
+"""Xen management daemon. Lives in /usr/sbin.
+   Provides console server and HTTP management api.
+
+   Run:
+
+   xend start
+
+   The daemon is stopped with:
+
+   xend stop
+
+   The daemon should reconnect to device control interfaces
+   and recover its state when restarted.
+"""
+import os
+import sys
+from xen.xend.server import SrvDaemon
+
+def main():
+    daemon = SrvDaemon.instance()
+    if not sys.argv[1:]:
+        print 'usage: %s {start|stop|restart}' % sys.argv[0]
+    elif os.fork():
+        pid, status = os.wait()
+        return status >> 8
+    elif sys.argv[1] == 'start':
+        return daemon.start()
+    elif sys.argv[1] == 'trace_start':
+        return daemon.start(trace=1)
+    elif sys.argv[1] == 'stop':
+        return daemon.stop()
+    elif sys.argv[1] == 'restart':
+        return daemon.stop() or daemon.start()
+    else:
+        print 'not an option:', sys.argv[1]
+    return 1
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/tools/misc/xm b/tools/misc/xm
new file mode 100755 (executable)
index 0000000..6ace888
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+#  -*- mode: python; -*-
+import sys
+from xen.xm import main
+
+main.main(sys.argv)
diff --git a/tools/python/Makefile b/tools/python/Makefile
new file mode 100644 (file)
index 0000000..7dc74a1
--- /dev/null
@@ -0,0 +1,15 @@
+
+all:
+       python setup.py build
+
+install: all
+       if [ "$(prefix)" = "" ]; then                   \
+           python setup.py install;                    \
+       elif [ "$(dist)" = "yes" ]; then                \
+           python setup.py install --home="$(prefix)"; \
+       else                                            \
+           python setup.py install --root="$(prefix)"; \
+       fi
+
+clean:
+       rm -rf build *.pyc *.pyo *.o *.a *~
diff --git a/tools/python/setup.py b/tools/python/setup.py
new file mode 100644 (file)
index 0000000..b0eb3f2
--- /dev/null
@@ -0,0 +1,48 @@
+
+from distutils.core import setup, Extension
+
+XEN_ROOT = "../.."
+
+extra_compile_args  = ["-fno-strict-aliasing"]
+
+
+include_dirs = [ XEN_ROOT + "/xen/include/hypervisor-ifs",
+                 XEN_ROOT + "/linux-xen-sparse/include",
+                 XEN_ROOT + "/tools/python/xen/ext/xu",
+                 XEN_ROOT + "/tools/libxc",
+                 XEN_ROOT + "/tools/libxutil",
+                 ]
+
+library_dirs = [ XEN_ROOT + "/tools/libxc",
+                 XEN_ROOT + "/tools/libxutil",
+                 ]
+
+libraries = [ "xc", "xutil" ]
+
+xc = Extension("xc",
+               extra_compile_args = extra_compile_args,
+               include_dirs       = include_dirs + [ "xen/ext/xc" ],
+               library_dirs       = library_dirs,
+               libraries          = libraries,
+               sources            = [ "xen/ext/xc/xc.c" ])
+
+xu = Extension("xu",
+               extra_compile_args = extra_compile_args,
+               include_dirs       = include_dirs + [ "xen/ext/xu" ],
+               library_dirs       = library_dirs,
+               libraries          = libraries,
+               sources            = [ "xen/ext/xu/xu.c" ])
+               
+setup(name            = 'xen',
+      version         = '2.0',
+      description     = 'Xen',
+      packages        = ['xen',
+                         'xen.ext',
+                         'xen.util',
+                         'xen.xend',
+                         'xen.xend.server',
+                         'xen.xm',
+                         ],
+      ext_package = "xen.ext",
+      ext_modules = [ xc, xu ]
+      )
diff --git a/tools/python/xen/__init__.py b/tools/python/xen/__init__.py
new file mode 100644 (file)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/tools/python/xen/ext/__init__.py b/tools/python/xen/ext/__init__.py
new file mode 100644 (file)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/tools/python/xen/ext/xc/Makefile b/tools/python/xen/ext/xc/Makefile
new file mode 100644 (file)
index 0000000..7dc74a1
--- /dev/null
@@ -0,0 +1,15 @@
+
+all:
+       python setup.py build
+
+install: all
+       if [ "$(prefix)" = "" ]; then                   \
+           python setup.py install;                    \
+       elif [ "$(dist)" = "yes" ]; then                \
+           python setup.py install --home="$(prefix)"; \
+       else                                            \
+           python setup.py install --root="$(prefix)"; \
+       fi
+
+clean:
+       rm -rf build *.pyc *.pyo *.o *.a *~
diff --git a/tools/python/xen/ext/xc/setup.py b/tools/python/xen/ext/xc/setup.py
new file mode 100644 (file)
index 0000000..8efe5ca
--- /dev/null
@@ -0,0 +1,19 @@
+
+from distutils.core import setup, Extension
+
+module = Extension("xc",
+                   extra_compile_args   = ["-fno-strict-aliasing"],
+                   include_dirs         = ["../lib",
+                                           "../../../xen/include/hypervisor-ifs",
+                                           "../../../linux-xen-sparse/include",
+                                           "../../xu/lib",
+                                           "../../lib" ],
+                   library_dirs         = ["../lib",
+                                           "../../lib" ],
+                   libraries            = ["xc"],
+                   sources              = ["Xc.c"])
+
+setup(name = "xc",
+      version = "2.0",
+      ext_package = "xen.ext",
+      ext_modules = [module])
diff --git a/tools/python/xen/ext/xc/xc.c b/tools/python/xen/ext/xc/xc.c
new file mode 100644 (file)
index 0000000..2eb70cf
--- /dev/null
@@ -0,0 +1,1160 @@
+/******************************************************************************
+ * Xc.c
+ * 
+ * Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
+ */
+
+#include <Python.h>
+#include <xc.h>
+#include <zlib.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include "xc_private.h"
+#include "gzip_stream.h"
+
+/* Needed for Python versions earlier than 2.3. */
+#ifndef PyMODINIT_FUNC
+#define PyMODINIT_FUNC DL_EXPORT(void)
+#endif
+
+#define XENPKG "xen.ext.xc"
+
+static PyObject *xc_error, *zero;
+
+typedef struct {
+    PyObject_HEAD;
+    int xc_handle;
+} XcObject;
+
+/*
+ * Definitions for the 'xc' object type.
+ */
+
+static PyObject *pyxc_domain_create(PyObject *self,
+                                    PyObject *args,
+                                    PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    unsigned int mem_kb = 0;
+    char        *name   = "(anon)";
+    int          cpu = -1;
+    u32          dom;
+    int          ret;
+
+    static char *kwd_list[] = { "mem_kb", "name", "cpu", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|isi", kwd_list, 
+                                      &mem_kb, &name, &cpu) )
+        return NULL;
+
+    if ( (ret = xc_domain_create(xc->xc_handle, mem_kb, name, cpu, &dom)) < 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return PyInt_FromLong(dom);
+}
+
+static PyObject *pyxc_domain_pause(PyObject *self,
+                                   PyObject *args,
+                                   PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+
+    static char *kwd_list[] = { "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+        return NULL;
+
+    if ( xc_domain_pause(xc->xc_handle, dom) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_domain_unpause(PyObject *self,
+                                     PyObject *args,
+                                     PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+
+    static char *kwd_list[] = { "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+        return NULL;
+
+    if ( xc_domain_unpause(xc->xc_handle, dom) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_domain_destroy(PyObject *self,
+                                     PyObject *args,
+                                     PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+
+    static char *kwd_list[] = { "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+        return NULL;
+
+    if ( xc_domain_destroy(xc->xc_handle, dom) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_domain_pincpu(PyObject *self,
+                                    PyObject *args,
+                                    PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+    int cpu = -1;
+
+    static char *kwd_list[] = { "dom", "cpu", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
+                                      &dom, &cpu) )
+        return NULL;
+
+    if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_domain_getinfo(PyObject *self,
+                                     PyObject *args,
+                                     PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    PyObject *list;
+
+    u32 first_dom = 0;
+    int max_doms = 1024, nr_doms, i;
+    xc_dominfo_t *info;
+
+    static char *kwd_list[] = { "first_dom", "max_doms", NULL };
+    
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
+                                      &first_dom, &max_doms) )
+        return NULL;
+
+    if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
+        return PyErr_NoMemory();
+
+    nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
+    
+    list = PyList_New(nr_doms);
+    for ( i = 0 ; i < nr_doms; i++ )
+    {
+        PyList_SetItem(
+            list, i, 
+            Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
+                          ",s:l,s:L,s:s,s:l,s:i}",
+                          "dom",       info[i].domid,
+                          "cpu",       info[i].cpu,
+                          "dying",     info[i].dying,
+                          "crashed",   info[i].crashed,
+                          "shutdown",  info[i].shutdown,
+                          "paused",    info[i].paused,
+                          "blocked",   info[i].blocked,
+                          "running",   info[i].running,
+                          "mem_kb",    info[i].nr_pages*4,
+                          "cpu_time",  info[i].cpu_time,
+                          "name",      info[i].name,
+                          "maxmem_kb", info[i].max_memkb,
+                          "shutdown_reason", info[i].shutdown_reason
+                ));
+    }
+
+    free(info);
+
+    return list;
+}
+
+static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file){
+    int rc = -1;
+    int fd = -1;
+    int open_flags = (O_CREAT | O_EXCL | O_WRONLY);
+    int open_mode = 0644;
+
+    printf("%s>\n", __FUNCTION__);
+    fd = open(state_file, open_flags, open_mode);
+    if(fd < 0){
+        xcio_perror(ctxt, "Could not open file for writing");
+        goto exit;
+    }
+    /* Compression rate 1: we want speed over compression. 
+     * We're mainly going for those zero pages, after all.
+     */
+    printf("%s>gzip_stream_fdopen... \n", __FUNCTION__);
+    ctxt->io = gzip_stream_fdopen(fd, "wb1");
+    if(!ctxt->io){
+        xcio_perror(ctxt, "Could not allocate compression state");
+        goto exit;
+    }
+    printf("%s> xc_linux_save...\n", __FUNCTION__);
+    rc = xc_linux_save(xc->xc_handle, ctxt);
+  exit:
+    if(ctxt->io) IOStream_close(ctxt->io);
+    if(fd >= 0) close(fd);
+    unlink(state_file);
+    printf("%s> rc=%d\n", __FUNCTION__, rc);
+    return rc;
+}
+
+static PyObject *pyxc_linux_save(PyObject *self,
+                                 PyObject *args,
+                                 PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+    char *state_file;
+    int progress = 1, debug = 0;
+    unsigned int flags = 0;
+    PyObject *val = NULL;
+    int rc = -1;
+    XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
+
+    static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL };
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|sii", kwd_list, 
+                                     &ioctxt.domain,
+                                     &state_file,
+                                     &ioctxt.vmconfig,
+                                     &progress, 
+                                     &debug)){
+        goto exit;
+    }
+    ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0);
+    if (progress)  ioctxt.flags |= XCFLAGS_VERBOSE;
+    if (debug)     ioctxt.flags |= XCFLAGS_DEBUG;
+    if(!state_file || state_file[0] == '\0') goto exit;
+    rc = file_save(xc, &ioctxt, state_file);
+    if(rc){
+        PyErr_SetFromErrno(xc_error);
+        goto exit;
+    } 
+    //xc_domain_destroy(xc->xc_handle, dom);
+    Py_INCREF(zero);
+    val = zero;
+  exit:
+    return val;
+}
+
+
+static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file){
+    int rc = -1;
+
+    ioctxt->io = gzip_stream_fopen(state_file, "rb");
+    if (!ioctxt->io) {
+        xcio_perror(ioctxt, "Could not open file for reading");
+        goto exit;
+    }
+
+    rc = xc_linux_restore(xc->xc_handle, ioctxt);
+  exit:
+    if(ioctxt->io) IOStream_close(ioctxt->io);
+    return rc;
+}
+
+static PyObject *pyxc_linux_restore(PyObject *self,
+                                    PyObject *args,
+                                    PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    char *state_file;
+    int progress = 1, debug = 0;
+    u32 dom;
+    PyObject *val = NULL;
+    XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
+    int rc =-1;
+
+    static char *kwd_list[] = { "state_file", "progress", "debug", NULL };
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|ii", kwd_list, 
+                                     &ioctxt.domain,
+                                     &state_file,
+                                     &progress,
+                                     &debug)){
+        goto exit;
+    }
+    if (progress) ioctxt.flags |= XCFLAGS_VERBOSE;
+    if (debug)    ioctxt.flags |= XCFLAGS_DEBUG;
+
+    if(!state_file || state_file[0] == '\0') goto exit;
+    rc = file_restore(xc, &ioctxt, state_file);
+    if(rc){
+        PyErr_SetFromErrno(xc_error);
+        goto exit;
+    }
+    val = Py_BuildValue("{s:i,s:s}",
+                        "dom", ioctxt.domain,
+                        "vmconfig", ioctxt.vmconfig);
+    //? free(ioctxt.vmconfig);
+  exit:
+    return val;
+}
+
+static PyObject *pyxc_linux_build(PyObject *self,
+                                  PyObject *args,
+                                  PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32   dom;
+    char *image, *ramdisk = NULL, *cmdline = "";
+    int   control_evtchn, flags = 0;
+
+    static char *kwd_list[] = { "dom", "control_evtchn", 
+                                "image", "ramdisk", "cmdline", "flags",
+                                NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, 
+                                      &dom, &control_evtchn, 
+                                      &image, &ramdisk, &cmdline, &flags) )
+        return NULL;
+
+    if ( xc_linux_build(xc->xc_handle, dom, image,
+                        ramdisk, cmdline, control_evtchn, flags) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_netbsd_build(PyObject *self,
+                                   PyObject *args,
+                                   PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32   dom;
+    char *image, *ramdisk = NULL, *cmdline = "";
+    int   control_evtchn;
+
+    static char *kwd_list[] = { "dom", "control_evtchn",
+                                "image", "ramdisk", "cmdline", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, 
+                                      &dom, &control_evtchn,
+                                      &image, &ramdisk, &cmdline) )
+        return NULL;
+
+    if ( xc_netbsd_build(xc->xc_handle, dom, image, 
+                         cmdline, control_evtchn) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_bvtsched_global_set(PyObject *self,
+                                          PyObject *args,
+                                          PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    unsigned long ctx_allow;
+
+    static char *kwd_list[] = { "ctx_allow", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
+        return NULL;
+
+    if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_bvtsched_global_get(PyObject *self,
+                                          PyObject *args,
+                                          PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    
+    unsigned long ctx_allow;
+    
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+    
+    if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
+}
+
+static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
+                                          PyObject *args,
+                                          PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32           dom;
+    unsigned long mcuadv, warp, warpl, warpu;
+
+    static char *kwd_list[] = { "dom", "mcuadv", "warp", "warpl",
+                                "warpu", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illll", kwd_list,
+                                      &dom, &mcuadv, &warp, &warpl, &warpu) )
+        return NULL;
+
+    if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv, 
+                                warp, warpl, warpu) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
+                                          PyObject *args,
+                                          PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u32 dom;
+    unsigned long mcuadv, warp, warpl, warpu;
+    
+    static char *kwd_list[] = { "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
+        return NULL;
+    
+    if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warp,
+                                &warpl, &warpu) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
+                         "domain", dom,
+                         "mcuadv", mcuadv,
+                         "warp",   warp,
+                         "warpl",  warpl,
+                         "warpu",  warpu);
+}
+
+static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
+                                              PyObject *args,
+                                              PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
+    int port1, port2;
+
+    static char *kwd_list[] = { "dom1", "dom2", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list, 
+                                      &dom1, &dom2) )
+        return NULL;
+
+    if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1, 
+                                    dom2, &port1, &port2) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return Py_BuildValue("{s:i,s:i}", 
+                         "port1", port1,
+                         "port2", port2);
+}
+
+static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
+                                       PyObject *args,
+                                       PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    int virq, port;
+
+    static char *kwd_list[] = { "virq", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
+        return NULL;
+
+    if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return PyInt_FromLong(port);
+}
+
+static PyObject *pyxc_evtchn_close(PyObject *self,
+                                   PyObject *args,
+                                   PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom = DOMID_SELF;
+    int port;
+
+    static char *kwd_list[] = { "port", "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
+                                      &port, &dom) )
+        return NULL;
+
+    if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_evtchn_send(PyObject *self,
+                                  PyObject *args,
+                                  PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    int port;
+
+    static char *kwd_list[] = { "port", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
+        return NULL;
+
+    if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_evtchn_status(PyObject *self,
+                                    PyObject *args,
+                                    PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    PyObject *dict;
+
+    u32 dom = DOMID_SELF;
+    int port, ret;
+    xc_evtchn_status_t status;
+
+    static char *kwd_list[] = { "port", "dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
+                                      &port, &dom) )
+        return NULL;
+
+    ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
+    if ( ret != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    switch ( status.status )
+    {
+    case EVTCHNSTAT_closed:
+        dict = Py_BuildValue("{s:s}", 
+                             "status", "closed");
+        break;
+    case EVTCHNSTAT_unbound:
+        dict = Py_BuildValue("{s:s}", 
+                             "status", "unbound");
+        break;
+    case EVTCHNSTAT_interdomain:
+        dict = Py_BuildValue("{s:s,s:i,s:i}", 
+                             "status", "interdomain",
+                             "dom", status.u.interdomain.dom,
+                             "port", status.u.interdomain.port);
+        break;
+    case EVTCHNSTAT_pirq:
+        dict = Py_BuildValue("{s:s,s:i}", 
+                             "status", "pirq",
+                             "irq", status.u.pirq);
+        break;
+    case EVTCHNSTAT_virq:
+        dict = Py_BuildValue("{s:s,s:i}", 
+                             "status", "virq",
+                             "irq", status.u.virq);
+        break;
+    default:
+        dict = Py_BuildValue("{}");
+        break;
+    }
+    
+    return dict;
+}
+
+static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
+                                                PyObject *args,
+                                                PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u32 dom;
+    int bus, dev, func, enable, ret;
+
+    static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list, 
+                                      &dom, &bus, &dev, &func, &enable) )
+        return NULL;
+
+    ret = xc_physdev_pci_access_modify(
+        xc->xc_handle, dom, bus, dev, func, enable);
+    if ( ret != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_readconsolering(PyObject *self,
+                                      PyObject *args,
+                                      PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    unsigned int clear = 0;
+    char         str[32768];
+    int          ret;
+
+    static char *kwd_list[] = { "clear", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
+        return NULL;
+
+    ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
+    if ( ret < 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return PyString_FromStringAndSize(str, ret);
+}
+
+static PyObject *pyxc_physinfo(PyObject *self,
+                               PyObject *args,
+                               PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    xc_physinfo_t info;
+    
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( xc_physinfo(xc->xc_handle, &info) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
+                         "ht_per_core", info.ht_per_core,
+                         "cores",       info.cores,
+                         "total_pages", info.total_pages,
+                         "free_pages",  info.free_pages,
+                         "cpu_khz",     info.cpu_khz);
+}
+
+static PyObject *pyxc_atropos_domain_set(PyObject *self,
+                                         PyObject *args,
+                                         PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u32 domid;
+    u64 period, slice, latency;
+    int xtratime;
+
+    static char *kwd_list[] = { "dom", "period", "slice", "latency",
+                                "xtratime", NULL };
+    
+    if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLi", kwd_list, &domid,
+                                     &period, &slice, &latency, &xtratime) )
+        return NULL;
+   
+    if ( xc_atropos_domain_set(xc->xc_handle, domid, period, slice,
+                               latency, xtratime) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_atropos_domain_get(PyObject *self,
+                                         PyObject *args,
+                                         PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u32 domid;
+    u64 period, slice, latency;
+    int xtratime;
+    
+    static char *kwd_list[] = { "dom", NULL };
+
+    if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
+        return NULL;
+    
+    if ( xc_atropos_domain_get( xc->xc_handle, domid, &period,
+                                &slice, &latency, &xtratime ) )
+        return PyErr_SetFromErrno(xc_error);
+
+    return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
+                         "domain",  domid,
+                         "period",  period,
+                         "slice",   slice,
+                         "latency", latency,
+                         "xtratime", xtratime);
+}
+
+
+static PyObject *pyxc_rrobin_global_set(PyObject *self,
+                                        PyObject *args,
+                                        PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u64 slice;
+    
+    static char *kwd_list[] = { "slice", NULL };
+
+    if( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &slice) )
+        return NULL;
+    
+    if ( xc_rrobin_global_set(xc->xc_handle, slice) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_shadow_control(PyObject *self,
+                                     PyObject *args,
+                                     PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+    int op=0;
+
+    static char *kwd_list[] = { "dom", "op", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
+                                      &dom, &op) )
+        return NULL;
+
+    if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_rrobin_global_get(PyObject *self,
+                                        PyObject *args,
+                                        PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u64 slice;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( xc_rrobin_global_get(xc->xc_handle, &slice) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    return Py_BuildValue("{s:L}", "slice", slice);
+}
+
+static PyObject *pyxc_domain_setname(PyObject *self,
+                                     PyObject *args,
+                                     PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    u32 dom;
+    char *name;
+
+    static char *kwd_list[] = { "dom", "name", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is", kwd_list, 
+                                      &dom, &name) )
+        return NULL;
+
+    if ( xc_domain_setname(xc->xc_handle, dom, name) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_domain_setmaxmem(PyObject *self,
+                                       PyObject *args,
+                                       PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    u32 dom;
+    unsigned long max_memkb;
+
+    static char *kwd_list[] = { "dom", "max_memkb", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, 
+                                      &dom, &max_memkb) )
+        return NULL;
+
+    if ( xc_domain_setmaxmem(xc->xc_handle, dom, max_memkb) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
+}
+
+
+static PyMethodDef pyxc_methods[] = {
+    { "domain_create", 
+      (PyCFunction)pyxc_domain_create, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Create a new domain.\n"
+      " mem_kb [int, 0]:        Memory allocation, in kilobytes.\n"
+      " name   [str, '(anon)']: Informative textual name.\n\n"
+      "Returns: [int] new domain identifier; -1 on error.\n" },
+
+    { "domain_pause", 
+      (PyCFunction)pyxc_domain_pause, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Temporarily pause execution of a domain.\n"
+      " dom [int]: Identifier of domain to be paused.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_unpause", 
+      (PyCFunction)pyxc_domain_unpause, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "(Re)start execution of a domain.\n"
+      " dom [int]: Identifier of domain to be unpaused.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_destroy", 
+      (PyCFunction)pyxc_domain_destroy, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Destroy a domain.\n"
+      " dom [int]:    Identifier of domain to be destroyed.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_pincpu", 
+      (PyCFunction)pyxc_domain_pincpu, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Pin a domain to a specified CPU.\n"
+      " dom [int]:     Identifier of domain to be pinned.\n"
+      " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_getinfo", 
+      (PyCFunction)pyxc_domain_getinfo, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Get information regarding a set of domains, in increasing id order.\n"
+      " first_dom [int, 0]:    First domain to retrieve info about.\n"
+      " max_doms  [int, 1024]: Maximum number of domains to retrieve info"
+      " about.\n\n"
+      "Returns: [list of dicts] if list length is less than 'max_doms'\n"
+      "         parameter then there was an error, or the end of the\n"
+      "         domain-id space was reached.\n"
+      " dom      [int]: Identifier of domain to which this info pertains\n"
+      " cpu      [int]:  CPU to which this domain is bound\n"
+      " dying    [int]:  Bool - is the domain dying?\n"
+      " crashed  [int]:  Bool - has the domain crashed?\n"
+      " shutdown [int]:  Bool - has the domain shut itself down?\n"
+      " paused   [int]:  Bool - is the domain paused by control software?\n"
+      " blocked  [int]:  Bool - is the domain blocked waiting for an event?\n"
+      " running  [int]:  Bool - is the domain currently running?\n"
+      " mem_kb   [int]:  Memory reservation, in kilobytes\n"
+      " cpu_time [long]: CPU time consumed, in nanoseconds\n"
+      " name     [str]:  Identifying name\n"
+      " shutdown_reason [int]: Numeric code from guest OS, explaining "
+      "reason why it shut itself down.\n" },
+
+    { "linux_save", 
+      (PyCFunction)pyxc_linux_save, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Save the CPU and memory state of a Linux guest OS.\n"
+      " dom        [int]:    Identifier of domain to be saved.\n"
+      " state_file [str]:    Name of state file. Must not currently exist.\n"
+      " progress   [int, 1]: Bool - display a running progress indication?\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "linux_restore", 
+      (PyCFunction)pyxc_linux_restore, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Restore the CPU and memory state of a Linux guest OS.\n"
+      " state_file [str]:    Name of state file. Must not currently exist.\n"
+      " progress   [int, 1]: Bool - display a running progress indication?\n\n"
+      "Returns: [int] new domain identifier on success; -1 on error.\n" },
+
+    { "linux_build", 
+      (PyCFunction)pyxc_linux_build, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Build a new Linux guest OS.\n"
+      " dom     [int]:      Identifier of domain to build into.\n"
+      " image   [str]:      Name of kernel image file. May be gzipped.\n"
+      " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
+      " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "netbsd_build", 
+      (PyCFunction)pyxc_netbsd_build, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Build a new NetBSD guest OS.\n"
+      " dom     [int]:     Identifier of domain to build into.\n"
+      " image   [str]:      Name of kernel image file. May be gzipped.\n"
+      " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "bvtsched_global_set",
+      (PyCFunction)pyxc_bvtsched_global_set,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
+      " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "bvtsched_global_get",
+      (PyCFunction)pyxc_bvtsched_global_get,
+      METH_KEYWORDS, "\n"
+      "Get global tuning parameters for BVT scheduler.\n"
+      "Returns: [dict]:\n"
+      " ctx_allow [int]: context switch allowance\n" },
+
+    { "bvtsched_domain_set",
+      (PyCFunction)pyxc_bvtsched_domain_set,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
+      " dom    [int]: Identifier of domain to be tuned.\n"
+      " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
+      " warp   [int]: How far to warp domain's EVT on unblock.\n"
+      " warpl  [int]: How long the domain can run warped.\n"
+      " warpu  [int]: How long before the domain can warp again.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "bvtsched_domain_get",
+      (PyCFunction)pyxc_bvtsched_domain_get,
+      METH_KEYWORDS, "\n"
+      "Get per-domain tuning parameters under the BVT scheduler.\n"
+      " dom [int]: Identifier of domain to be queried.\n"
+      "Returns [dict]:\n"
+      " domain [int]:  Domain ID.\n"
+      " mcuadv [long]: MCU Advance.\n"
+      " warp   [long]: Warp.\n"
+      " warpu  [long]: Unwarp requirement.\n"
+      " warpl  [long]: Warp limit,\n"
+    },
+
+    { "atropos_domain_set",
+      (PyCFunction)pyxc_atropos_domain_set,
+      METH_KEYWORDS, "\n"
+      "Set the scheduling parameters for a domain when running with Atropos.\n"
+      " dom      [int]:  domain to set\n"
+      " period   [long]: domain's scheduling period\n"
+      " slice    [long]: domain's slice per period\n"
+      " latency  [long]: wakeup latency hint\n"
+      " xtratime [int]: boolean\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "atropos_domain_get",
+      (PyCFunction)pyxc_atropos_domain_get,
+      METH_KEYWORDS, "\n"
+      "Get the current scheduling parameters for a domain when running with\n"
+      "the Atropos scheduler."
+      " dom      [int]: domain to query\n"
+      "Returns:  [dict]\n"
+      " domain   [int]: domain ID\n"
+      " period   [long]: scheduler period\n"
+      " slice    [long]: CPU reservation per period\n"
+      " latency  [long]: unblocking latency hint\n"
+      " xtratime [int] : 0 if not using slack time, nonzero otherwise\n" },
+
+    { "rrobin_global_set",
+      (PyCFunction)pyxc_rrobin_global_set,
+      METH_KEYWORDS, "\n"
+      "Set Round Robin scheduler slice.\n"
+      " slice [long]: Round Robin scheduler slice\n"
+      "Returns: [int] 0 on success, throws an exception on failure\n" },
+
+    { "rrobin_global_get",
+      (PyCFunction)pyxc_rrobin_global_get,
+      METH_KEYWORDS, "\n"
+      "Get Round Robin scheduler settings\n"
+      "Returns [dict]:\n"
+      " slice  [long]: Scheduler time slice.\n" },    
+
+    { "evtchn_bind_interdomain", 
+      (PyCFunction)pyxc_evtchn_bind_interdomain, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Open an event channel between two domains.\n"
+      " dom1 [int, SELF]: First domain to be connected.\n"
+      " dom2 [int, SELF]: Second domain to be connected.\n\n"
+      "Returns: [dict] dictionary is empty on failure.\n"
+      " port1 [int]: Port-id for endpoint at dom1.\n"
+      " port2 [int]: Port-id for endpoint at dom2.\n" },
+
+    { "evtchn_bind_virq", 
+      (PyCFunction)pyxc_evtchn_bind_virq, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Bind an event channel to the specified VIRQ.\n"
+      " virq [int]: VIRQ to bind.\n\n"
+      "Returns: [int] Bound event-channel port.\n" },
+
+    { "evtchn_close", 
+      (PyCFunction)pyxc_evtchn_close, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Close an event channel.\n"
+      " dom  [int, SELF]: Dom-id of one endpoint of the channel.\n"
+      " port [int]:       Port-id of one endpoint of the channel.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "evtchn_send", 
+      (PyCFunction)pyxc_evtchn_send, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Send an event along a locally-connected event channel.\n"
+      " port [int]: Port-id of a local channel endpoint.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "evtchn_status", 
+      (PyCFunction)pyxc_evtchn_status, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Query the status of an event channel.\n"
+      " dom  [int, SELF]: Dom-id of one endpoint of the channel.\n"
+      " port [int]:       Port-id of one endpoint of the channel.\n\n"
+      "Returns: [dict] dictionary is empty on failure.\n"
+      " status [str]:  'closed', 'unbound', 'interdomain', 'pirq',"
+      " or 'virq'.\n"
+      "The following are returned if 'status' is 'interdomain':\n"
+      " dom  [int]: Dom-id of remote endpoint.\n"
+      " port [int]: Port-id of remote endpoint.\n"
+      "The following are returned if 'status' is 'pirq' or 'virq':\n"
+      " irq  [int]: IRQ number.\n" },
+
+    { "physdev_pci_access_modify",
+      (PyCFunction)pyxc_physdev_pci_access_modify,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Allow a domain access to a PCI device\n"
+      " dom    [int]: Identifier of domain to be allowed access.\n"
+      " bus    [int]: PCI bus\n"
+      " dev    [int]: PCI slot\n"
+      " func   [int]: PCI function\n"
+      " enable [int]: Non-zero means enable access; else disable access\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+    { "readconsolering", 
+      (PyCFunction)pyxc_readconsolering, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Read Xen's console ring.\n"
+      " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
+      "Returns: [str] string is empty on failure.\n" },
+
+    { "physinfo",
+      (PyCFunction)pyxc_physinfo,
+      METH_VARARGS, "\n"
+      "Get information about the physical host machine\n"
+      "Returns [dict]: information about the hardware"
+      "        [None]: on failure.\n" },
+
+    { "shadow_control", 
+      (PyCFunction)pyxc_shadow_control, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Set parameter for shadow pagetable interface\n"
+      " dom [int]:   Identifier of domain.\n"
+      " op [int, 0]: operation\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_setname", 
+      (PyCFunction)pyxc_domain_setname, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Set domain informative textual name\n"
+      " dom [int]:  Identifier of domain.\n"
+      " name [str]: Text string.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_setmaxmem", 
+      (PyCFunction)pyxc_domain_setname, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Set a domain's memory limit\n"
+      " dom [int]: Identifier of domain.\n"
+      " max_memkb [long]: .\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+
+/*
+ * Definitions for the 'Xc' module wrapper.
+ */
+
+staticforward PyTypeObject PyXcType;
+
+static PyObject *PyXc_new(PyObject *self, PyObject *args)
+{
+    XcObject *xc;
+
+    if ( !PyArg_ParseTuple(args, ":new") )
+        return NULL;
+
+    xc = PyObject_New(XcObject, &PyXcType);
+
+    if ( (xc->xc_handle = xc_interface_open()) == -1 )
+    {
+        PyObject_Del((PyObject *)xc);
+        return PyErr_SetFromErrno(xc_error);
+    }
+
+    return (PyObject *)xc;
+}
+
+static PyObject *PyXc_getattr(PyObject *obj, char *name)
+{
+    return Py_FindMethod(pyxc_methods, obj, name);
+}
+
+static void PyXc_dealloc(PyObject *self)
+{
+    XcObject *xc = (XcObject *)self;
+    (void)xc_interface_close(xc->xc_handle);
+    PyObject_Del(self);
+}
+
+static PyTypeObject PyXcType = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "Xc",
+    sizeof(XcObject),
+    0,
+    PyXc_dealloc,    /* tp_dealloc     */
+    NULL,            /* tp_print       */
+    PyXc_getattr,    /* tp_getattr     */
+    NULL,            /* tp_setattr     */
+    NULL,            /* tp_compare     */
+    NULL,            /* tp_repr        */
+    NULL,            /* tp_as_number   */
+    NULL,            /* tp_as_sequence */
+    NULL,            /* tp_as_mapping  */
+    NULL             /* tp_hash        */
+};
+
+static PyMethodDef PyXc_methods[] = {
+    { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
+    { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC initxc(void)
+{
+    PyObject *m, *d;
+
+    m = Py_InitModule(XENPKG, PyXc_methods);
+
+    d = PyModule_GetDict(m);
+    xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
+    PyDict_SetItemString(d, "error", xc_error);
+
+    zero = PyInt_FromLong(0);
+}
diff --git a/tools/python/xen/ext/xu/__init__.py b/tools/python/xen/ext/xu/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/python/xen/ext/xu/domain_controller.h b/tools/python/xen/ext/xu/domain_controller.h
new file mode 100644 (file)
index 0000000..76dd164
--- /dev/null
@@ -0,0 +1,532 @@
+/******************************************************************************
+ * domain_controller.h
+ * 
+ * Interface to server controller (e.g., 'xend'). This header file defines the 
+ * interface that is shared with guest OSes.
+ * 
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#ifndef __DOMAIN_CONTROLLER_H__
+#define __DOMAIN_CONTROLLER_H__
+
+
+#ifndef BASIC_START_INFO
+#error "Xen header file hypervisor-if.h must already be included here."
+#endif
+
+
+/*
+ * EXTENDED BOOTSTRAP STRUCTURE FOR NEW DOMAINS.
+ */
+
+typedef struct {
+    BASIC_START_INFO;
+    u16 domain_controller_evtchn; /* 320 */
+} PACKED extended_start_info_t; /* 322 bytes */
+#define SIF_BLK_BE_DOMAIN (1<<4)  /* Is this a block backend domain? */
+#define SIF_NET_BE_DOMAIN (1<<5)  /* Is this a net backend domain? */
+
+
+/*
+ * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
+ * interpreted by control software to determine the appropriate action. These 
+ * are only really advisories: the controller can actually do as it likes.
+ */
+#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
+#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
+#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
+
+
+/*
+ * CONTROLLER MESSAGING INTERFACE.
+ */
+
+typedef struct {
+    u8 type;     /*  0: echoed in response */
+    u8 subtype;  /*  1: echoed in response */
+    u8 id;       /*  2: echoed in response */
+    u8 length;   /*  3: number of bytes in 'msg' */
+    u8 msg[60];  /*  4: type-specific message data */
+} PACKED control_msg_t; /* 64 bytes */
+
+#define CONTROL_RING_SIZE 8
+typedef u32 CONTROL_RING_IDX;
+#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
+
+typedef struct {
+    control_msg_t tx_ring[CONTROL_RING_SIZE];   /*    0: guest -> controller */
+    control_msg_t rx_ring[CONTROL_RING_SIZE];   /*  512: controller -> guest */
+    CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
+    CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
+} PACKED control_if_t; /* 1040 bytes */
+
+/*
+ * Top-level command types.
+ */
+#define CMSG_CONSOLE        0  /* Console                 */
+#define CMSG_BLKIF_BE       1  /* Block-device backend    */
+#define CMSG_BLKIF_FE       2  /* Block-device frontend   */
+#define CMSG_NETIF_BE       3  /* Network-device backend  */
+#define CMSG_NETIF_FE       4  /* Network-device frontend */
+#define CMSG_SHUTDOWN       6  /* Shutdown messages       */
+
+
+/******************************************************************************
+ * CONSOLE DEFINITIONS
+ */
+
+/*
+ * Subtypes for console messages.
+ */
+#define CMSG_CONSOLE_DATA       0
+
+
+/******************************************************************************
+ * BLOCK-INTERFACE FRONTEND DEFINITIONS
+ */
+
+/* Messages from domain controller to guest. */
+#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED   0
+
+/* Messages from guest to domain controller. */
+#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
+#define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
+#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
+
+/* These are used by both front-end and back-end drivers. */
+#define blkif_vdev_t   u16
+#define blkif_pdev_t   u16
+#define blkif_sector_t u64
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
+ *  Notify a guest about a status change on one of its block interfaces.
+ *  If the interface is DESTROYED or DOWN then the interface is disconnected:
+ *   1. The shared-memory frame is available for reuse.
+ *   2. Any unacknowledged messgaes pending on the interface were dropped.
+ */
+#define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
+#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
+#define BLKIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
+typedef struct {
+    u32 handle; /*  0 */
+    u32 status; /*  4 */
+    u16 evtchn; /*  8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
+} PACKED blkif_fe_interface_status_changed_t; /* 10 bytes */
+
+/*
+ * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the front-end driver is DOWN or UP.
+ *  When the driver goes DOWN then the controller will send no more
+ *  status-change notifications. When the driver comes UP then the controller
+ *  will send a notification for each interface that currently exists.
+ *  If the driver goes DOWN while interfaces are still UP, the domain
+ *  will automatically take the interfaces DOWN.
+ */
+#define BLKIF_DRIVER_STATUS_DOWN   0
+#define BLKIF_DRIVER_STATUS_UP     1
+typedef struct {
+    /* IN */
+    u32 status;        /*  0: BLKIF_DRIVER_STATUS_??? */
+    /* OUT */
+    /*
+     * Tells driver how many interfaces it should expect to immediately
+     * receive notifications about.
+     */
+    u32 nr_interfaces; /*  4 */
+} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_CONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_CONNECTED message.
+ */
+typedef struct {
+    u32      handle;      /*  0 */
+    u32      __pad;
+    memory_t shmem_frame; /*  8 */
+    MEMORY_PADDING;
+} PACKED blkif_fe_interface_connect_t; /* 16 bytes */
+
+/*
+ * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_DISCONNECTED message.
+ */
+typedef struct {
+    u32 handle; /*  0 */
+} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * BLOCK-INTERFACE BACKEND DEFINITIONS
+ */
+
+/* Messages from domain controller. */
+#define CMSG_BLKIF_BE_CREATE      0  /* Create a new block-device interface. */
+#define CMSG_BLKIF_BE_DESTROY     1  /* Destroy a block-device interface.    */
+#define CMSG_BLKIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
+#define CMSG_BLKIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
+#define CMSG_BLKIF_BE_VBD_CREATE  4  /* Create a new VBD for an interface.   */
+#define CMSG_BLKIF_BE_VBD_DESTROY 5  /* Delete a VBD from an interface.      */
+#define CMSG_BLKIF_BE_VBD_GROW    6  /* Append an extent to a given VBD.     */
+#define CMSG_BLKIF_BE_VBD_SHRINK  7  /* Remove last extent from a given VBD. */
+
+/* Messages to domain controller. */
+#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
+
+/*
+ * Message request/response definitions for block-device messages.
+ */
+
+typedef struct {
+    blkif_sector_t sector_start;   /*  0 */
+    blkif_sector_t sector_length;  /*  8 */
+    blkif_pdev_t   device;         /* 16 */
+    u16            __pad;          /* 18 */
+} PACKED blkif_extent_t; /* 20 bytes */
+
+/* Non-specific 'okay' return. */
+#define BLKIF_BE_STATUS_OKAY                0
+/* Non-specific 'error' return. */
+#define BLKIF_BE_STATUS_ERROR               1
+/* The following are specific error returns. */
+#define BLKIF_BE_STATUS_INTERFACE_EXISTS    2
+#define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
+#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
+#define BLKIF_BE_STATUS_VBD_EXISTS          5
+#define BLKIF_BE_STATUS_VBD_NOT_FOUND       6
+#define BLKIF_BE_STATUS_OUT_OF_MEMORY       7
+#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND    8
+#define BLKIF_BE_STATUS_MAPPING_ERROR       9
+
+/* This macro can be used to create an array of descriptive error strings. */
+#define BLKIF_BE_STATUS_ERRORS {    \
+    "Okay",                         \
+    "Non-specific error",           \
+    "Interface already exists",     \
+    "Interface not found",          \
+    "Interface is still connected", \
+    "VBD already exists",           \
+    "VBD not found",                \
+    "Out of memory",                \
+    "Extent not found for VBD",     \
+    "Could not map domain memory" }
+
+/*
+ * CMSG_BLKIF_BE_CREATE:
+ *  When the driver sends a successful response then the interface is fully
+ *  created. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED blkif_be_create_t; /* 12 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DESTROY:
+ *  When the driver sends a successful response then the interface is fully
+ *  torn down. The controller will send a DESTROYED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify interface to be destroyed. */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED blkif_be_destroy_t; /* 12 bytes */
+
+/*
+ * CMSG_BLKIF_BE_CONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  connected. The controller will send a CONNECTED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
+    memory_t   shmem_frame;   /*  8: Page cont. shared comms window.     */
+    MEMORY_PADDING;
+    u32        evtchn;        /* 16: Event channel for notifications.    */
+    /* OUT */
+    u32        status;        /* 20 */
+} PACKED blkif_be_connect_t;  /* 24 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DISCONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  disconnected. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED blkif_be_disconnect_t; /* 12 bytes */
+
+/* CMSG_BLKIF_BE_VBD_CREATE */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_vdev_t vdevice;     /*  8: Interface-specific id for this VBD. */
+    u16        readonly;      /* 10: Non-zero -> VBD isn't writeable.    */
+    /* OUT */
+    u32        status;        /* 12 */
+} PACKED blkif_be_vbd_create_t; /* 16 bytes */
+
+/* CMSG_BLKIF_BE_VBD_DESTROY */
+typedef struct {
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
+    u16        __pad;         /* 10 */
+    /* OUT */
+    u32        status;        /* 12 */
+} PACKED blkif_be_vbd_destroy_t; /* 16 bytes */
+
+/* CMSG_BLKIF_BE_VBD_GROW */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_extent_t extent;    /*  8: Physical extent to append to VBD.   */
+    blkif_vdev_t vdevice;     /* 28: Interface-specific id of the VBD.   */
+    u16        __pad;         /* 30 */
+    /* OUT */
+    u32        status;        /* 32 */
+} PACKED blkif_be_vbd_grow_t; /* 36 bytes */
+
+/* CMSG_BLKIF_BE_VBD_SHRINK */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify blkdev interface.          */
+    u32        blkif_handle;  /*  4: ...ditto...                         */
+    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
+    u16        __pad;         /* 10 */
+    /* OUT */
+    u32        status;        /* 12 */
+} PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
+
+/*
+ * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the back-end driver is DOWN or UP.
+ *  If the driver goes DOWN while interfaces are still UP, the controller
+ *  will automatically send DOWN notifications.
+ */
+typedef struct {
+    u32        status;        /*  0: BLKIF_DRIVER_STATUS_??? */
+} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * NETWORK-INTERFACE FRONTEND DEFINITIONS
+ */
+
+/* Messages from domain controller to guest. */
+#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED   0
+
+/* Messages from guest to domain controller. */
+#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
+#define CMSG_NETIF_FE_INTERFACE_CONNECT         33
+#define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
+ *  Notify a guest about a status change on one of its network interfaces.
+ *  If the interface is DESTROYED or DOWN then the interface is disconnected:
+ *   1. The shared-memory frame is available for reuse.
+ *   2. Any unacknowledged messgaes pending on the interface were dropped.
+ */
+#define NETIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
+#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
+#define NETIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
+typedef struct {
+    u32        handle; /*  0 */
+    u32        status; /*  4 */
+    u16        evtchn; /*  8: status == NETIF_INTERFACE_STATUS_CONNECTED */
+    u8         mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
+} PACKED netif_fe_interface_status_changed_t; /* 16 bytes */
+
+/*
+ * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the front-end driver is DOWN or UP.
+ *  When the driver goes DOWN then the controller will send no more
+ *  status-change notifications. When the driver comes UP then the controller
+ *  will send a notification for each interface that currently exists.
+ *  If the driver goes DOWN while interfaces are still UP, the domain
+ *  will automatically take the interfaces DOWN.
+ */
+#define NETIF_DRIVER_STATUS_DOWN   0
+#define NETIF_DRIVER_STATUS_UP     1
+typedef struct {
+    /* IN */
+    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
+    /* OUT */
+    /*
+     * Tells driver how many interfaces it should expect to immediately
+     * receive notifications about.
+     */
+    u32        nr_interfaces; /*  4 */
+} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_CONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_CONNECTED message.
+ */
+typedef struct {
+    u32        handle;         /*  0 */
+    u32        __pad;          /*  4 */
+    memory_t   tx_shmem_frame; /*  8 */
+    MEMORY_PADDING;
+    memory_t   rx_shmem_frame; /* 16 */
+    MEMORY_PADDING;
+} PACKED netif_fe_interface_connect_t; /* 24 bytes */
+
+/*
+ * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
+ *  If successful, the domain controller will acknowledge with a
+ *  STATUS_DISCONNECTED message.
+ */
+typedef struct {
+    u32        handle;        /*  0 */
+} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * NETWORK-INTERFACE BACKEND DEFINITIONS
+ */
+
+/* Messages from domain controller. */
+#define CMSG_NETIF_BE_CREATE      0  /* Create a new net-device interface. */
+#define CMSG_NETIF_BE_DESTROY     1  /* Destroy a net-device interface.    */
+#define CMSG_NETIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
+#define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
+
+/* Messages to domain controller. */
+#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
+
+/*
+ * Message request/response definitions for net-device messages.
+ */
+
+/* Non-specific 'okay' return. */
+#define NETIF_BE_STATUS_OKAY                0
+/* Non-specific 'error' return. */
+#define NETIF_BE_STATUS_ERROR               1
+/* The following are specific error returns. */
+#define NETIF_BE_STATUS_INTERFACE_EXISTS    2
+#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
+#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
+#define NETIF_BE_STATUS_OUT_OF_MEMORY       5
+#define NETIF_BE_STATUS_MAPPING_ERROR       6
+
+/* This macro can be used to create an array of descriptive error strings. */
+#define NETIF_BE_STATUS_ERRORS {    \
+    "Okay",                         \
+    "Non-specific error",           \
+    "Interface already exists",     \
+    "Interface not found",          \
+    "Interface is still connected", \
+    "Out of memory",                \
+    "Could not map domain memory" }
+
+/*
+ * CMSG_NETIF_BE_CREATE:
+ *  When the driver sends a successful response then the interface is fully
+ *  created. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
+    u8         mac[6];        /*  8 */
+    u16        __pad;         /* 14 */
+    /* OUT */
+    u32        status;        /* 16 */
+} PACKED netif_be_create_t; /* 20 bytes */
+
+/*
+ * CMSG_NETIF_BE_DESTROY:
+ *  When the driver sends a successful response then the interface is fully
+ *  torn down. The controller will send a DESTROYED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Identify interface to be destroyed. */
+    u32        netif_handle;  /*  4: ...ditto...                         */
+    /* OUT */
+    u32   status;             /*  8 */
+} PACKED netif_be_destroy_t; /* 12 bytes */
+
+/*
+ * CMSG_NETIF_BE_CONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  connected. The controller will send a CONNECTED notification to the
+ *  front-end driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;          /*  0: Domain attached to new interface.   */
+    u32        netif_handle;   /*  4: Domain-specific interface handle.   */
+    memory_t   tx_shmem_frame; /*  8: Page cont. tx shared comms window.  */
+    MEMORY_PADDING;
+    memory_t   rx_shmem_frame; /* 16: Page cont. rx shared comms window.  */
+    MEMORY_PADDING;
+    u16        evtchn;         /* 24: Event channel for notifications.    */
+    u16        __pad;          /* 26 */
+    /* OUT */
+    u32        status;         /* 28 */
+} PACKED netif_be_connect_t; /* 32 bytes */
+
+/*
+ * CMSG_NETIF_BE_DISCONNECT:
+ *  When the driver sends a successful response then the interface is fully
+ *  disconnected. The controller will send a DOWN notification to the front-end
+ *  driver.
+ */
+typedef struct { 
+    /* IN */
+    domid_t    domid;         /*  0: Domain attached to new interface.   */
+    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
+    /* OUT */
+    u32        status;        /*  8 */
+} PACKED netif_be_disconnect_t; /* 12 bytes */
+
+/*
+ * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
+ *  Notify the domain controller that the back-end driver is DOWN or UP.
+ *  If the driver goes DOWN while interfaces are still UP, the domain
+ *  will automatically send DOWN notifications.
+ */
+typedef struct {
+    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
+} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
+
+
+/******************************************************************************
+ * SHUTDOWN DEFINITIONS
+ */
+
+/*
+ * Subtypes for shutdown messages.
+ */
+#define CMSG_SHUTDOWN_POWEROFF  0   /* Clean shutdown (SHUTDOWN_poweroff).   */
+#define CMSG_SHUTDOWN_REBOOT    1   /* Clean shutdown (SHUTDOWN_reboot).     */
+#define CMSG_SHUTDOWN_SUSPEND   2   /* Create suspend info, then             */
+                                    /* SHUTDOWN_suspend.                     */
+
+#endif /* __DOMAIN_CONTROLLER_H__ */
diff --git a/tools/python/xen/ext/xu/xu.c b/tools/python/xen/ext/xu/xu.c
new file mode 100644 (file)
index 0000000..48c9759
--- /dev/null
@@ -0,0 +1,1386 @@
+/******************************************************************************
+ * utils.c
+ * 
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#include <Python.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <xc.h>
+
+#include <hypervisor-if.h>
+#include "domain_controller.h"
+
+#include <asm-xen/proc_cmd.h>
+
+#define XENPKG "xen.ext.xu"
+
+/* Needed for Python versions earlier than 2.3. */
+#ifndef PyMODINIT_FUNC
+#define PyMODINIT_FUNC DL_EXPORT(void)
+#endif
+
+/* NB. The following should be kept in sync with the kernel's evtchn driver. */
+#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
+#define EVTCHN_DEV_MAJOR 10
+#define EVTCHN_DEV_MINOR 200
+#define PORT_NORMAL     0x0000   /* A standard event notification.      */ 
+#define PORT_EXCEPTION  0x8000   /* An exceptional notification.        */
+#define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
+/* /dev/xen/evtchn ioctls: */
+/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
+#define EVTCHN_RESET  _IO('E', 1)
+/* EVTCHN_BIND: Bind to teh specified event-channel port. */
+#define EVTCHN_BIND   _IO('E', 2)
+/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
+#define EVTCHN_UNBIND _IO('E', 3)
+
+/* Size of a machine page frame. */
+#define PAGE_SIZE 4096
+
+
+/*
+ * *********************** NOTIFIER ***********************
+ */
+
+typedef struct {
+    PyObject_HEAD;
+    int evtchn_fd;
+} xu_notifier_object;
+
+static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    u16 v;
+    int bytes;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+    
+    while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
+    {
+        if ( errno == EINTR )
+            continue;
+        if ( errno == EAGAIN )
+            goto none;
+        return PyErr_SetFromErrno(PyExc_IOError);
+    }
+    
+    if ( bytes == sizeof(v) )
+        return Py_BuildValue("(i,i)", v&PORTIDX_MASK, v&~PORTIDX_MASK);
+
+ none:
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    u16 v;
+    int idx;
+
+    if ( !PyArg_ParseTuple(args, "i", &idx) )
+        return NULL;
+
+    v = (u16)idx;
+    
+    (void)write(xun->evtchn_fd, &v, sizeof(v));
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    int idx;
+
+    if ( !PyArg_ParseTuple(args, "i", &idx) )
+        return NULL;
+
+    if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
+        return PyErr_SetFromErrno(PyExc_IOError);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    int idx;
+
+    if ( !PyArg_ParseTuple(args, "i", &idx) )
+        return NULL;
+
+    if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
+        return PyErr_SetFromErrno(PyExc_IOError);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    return PyInt_FromLong(xun->evtchn_fd);
+}
+
+static PyMethodDef xu_notifier_methods[] = {
+    { "read",
+      (PyCFunction)xu_notifier_read,
+      METH_VARARGS,
+      "Read a (@port, @type) pair.\n" },
+
+    { "unmask", 
+      (PyCFunction)xu_notifier_unmask,
+      METH_VARARGS,
+      "Unmask notifications for a @port.\n" },
+
+    { "bind", 
+      (PyCFunction)xu_notifier_bind,
+      METH_VARARGS,
+      "Get notifications for a @port.\n" },
+
+    { "unbind", 
+      (PyCFunction)xu_notifier_unbind,
+      METH_VARARGS,
+      "No longer get notifications for a @port.\n" },
+
+    { "fileno", 
+      (PyCFunction)xu_notifier_fileno,
+      METH_VARARGS,
+      "Return the file descriptor for the notification channel.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_notifier_type;
+
+static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
+{
+    xu_notifier_object *xun;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
+
+ reopen:
+    xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
+    if ( xun->evtchn_fd == -1 )
+    {
+        if ( (errno == ENOENT) &&
+             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
+             (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, 
+                    (EVTCHN_DEV_MAJOR << 8) | EVTCHN_DEV_MINOR) == 0) )
+            goto reopen;
+        PyObject_Del((PyObject *)xun);
+        return PyErr_SetFromErrno(PyExc_IOError);
+    }
+
+    return (PyObject *)xun;
+}
+
+static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
+{
+    if ( strcmp(name, "EXCEPTION") == 0 )
+        return PyInt_FromLong(PORT_EXCEPTION);
+    if ( strcmp(name, "NORMAL") == 0 )
+        return PyInt_FromLong(PORT_NORMAL);
+    return Py_FindMethod(xu_notifier_methods, obj, name);
+}
+
+static void xu_notifier_dealloc(PyObject *self)
+{
+    xu_notifier_object *xun = (xu_notifier_object *)self;
+    (void)close(xun->evtchn_fd);
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_notifier_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "notifier",
+    sizeof(xu_notifier_object),
+    0,
+    xu_notifier_dealloc, /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_notifier_getattr, /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** MESSAGE ***********************
+ */
+
+#define TYPE(_x,_y) (((_x)<<8)|(_y))
+#define P2C(_struct, _field, _ctype)                                      \
+    do {                                                                  \
+        PyObject *obj;                                                    \
+        if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL )     \
+        {                                                                 \
+            if ( PyInt_Check(obj) )                                       \
+            {                                                             \
+                ((_struct *)&xum->msg.msg[0])->_field =                   \
+                  (_ctype)PyInt_AsLong(obj);                              \
+                dict_items_parsed++;                                      \
+            }                                                             \
+            else if ( PyLong_Check(obj) )                                 \
+            {                                                             \
+                ((_struct *)&xum->msg.msg[0])->_field =                   \
+                  (_ctype)PyLong_AsUnsignedLongLong(obj);                 \
+                dict_items_parsed++;                                      \
+            }                                                             \
+        }                                                                 \
+        xum->msg.length = sizeof(_struct);                                \
+    } while ( 0 )
+#define C2P(_struct, _field, _pytype, _ctype)                             \
+    do {                                                                  \
+        PyObject *obj = Py ## _pytype ## _From ## _ctype                  \
+                        (((_struct *)&xum->msg.msg[0])->_field);          \
+        if ( dict == NULL ) dict = PyDict_New();                          \
+        PyDict_SetItemString(dict, #_field, obj);                         \
+    } while ( 0 )
+
+typedef struct {
+    PyObject_HEAD;
+    control_msg_t msg;
+} xu_message_object;
+
+static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+    char *str;
+    int len;
+
+    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
+        return NULL;
+
+    if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
+    {
+        PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
+        return NULL;
+    }
+
+    memcpy(&xum->msg.msg[xum->msg.length], str, len);
+    xum->msg.length += len;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+    PyObject *payload;
+    int dict_items_parsed = 0;
+
+    if ( !PyArg_ParseTuple(args, "O", &payload) )
+        return NULL;
+
+    if ( !PyDict_Check(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
+        return NULL;
+    }
+
+    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
+    {
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
+        P2C(blkif_fe_driver_status_changed_t, nr_interfaces, u32);
+        break;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+        break;
+    }
+
+    if ( dict_items_parsed != PyDict_Size(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
+        return NULL;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+    PyObject *dict = NULL;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
+    {
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
+        C2P(blkif_fe_interface_status_changed_t, handle, Int, Long);
+        C2P(blkif_fe_interface_status_changed_t, status, Int, Long);
+        C2P(blkif_fe_interface_status_changed_t, evtchn, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
+        C2P(blkif_fe_driver_status_changed_t, status, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
+        C2P(blkif_fe_interface_connect_t, handle,      Int, Long);
+        C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
+        C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
+        C2P(blkif_be_create_t, domid,        Int, Long);
+        C2P(blkif_be_create_t, blkif_handle, Int, Long);
+        C2P(blkif_be_create_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
+        C2P(blkif_be_destroy_t, domid,        Int, Long);
+        C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
+        C2P(blkif_be_destroy_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
+        C2P(blkif_be_connect_t, domid,        Int, Long);
+        C2P(blkif_be_connect_t, blkif_handle, Int, Long);
+        C2P(blkif_be_connect_t, shmem_frame,  Int, Long);
+        C2P(blkif_be_connect_t, evtchn,       Int, Long);
+        C2P(blkif_be_connect_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
+        C2P(blkif_be_disconnect_t, domid,        Int, Long);
+        C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
+        C2P(blkif_be_disconnect_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
+        C2P(blkif_be_vbd_create_t, domid,        Int, Long);
+        C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
+        C2P(blkif_be_vbd_create_t, vdevice,      Int, Long);
+        C2P(blkif_be_vbd_create_t, readonly,     Int, Long);
+        C2P(blkif_be_vbd_create_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
+        C2P(blkif_be_vbd_destroy_t, domid,        Int, Long);
+        C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
+        C2P(blkif_be_vbd_destroy_t, vdevice,      Int, Long);
+        C2P(blkif_be_vbd_destroy_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
+        C2P(blkif_be_vbd_grow_t, domid,         Int, Long);
+        C2P(blkif_be_vbd_grow_t, blkif_handle,  Int, Long);
+        C2P(blkif_be_vbd_grow_t, vdevice,       Int, Long);
+        C2P(blkif_be_vbd_grow_t, extent.sector_start, 
+             Long, UnsignedLongLong);
+        C2P(blkif_be_vbd_grow_t, extent.sector_length, 
+             Long, UnsignedLongLong);
+        C2P(blkif_be_vbd_grow_t, extent.device, Int, Long);
+        C2P(blkif_be_vbd_grow_t, status,        Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
+        C2P(blkif_be_vbd_shrink_t, domid,        Int, Long);
+        C2P(blkif_be_vbd_shrink_t, blkif_handle, Int, Long);
+        C2P(blkif_be_vbd_shrink_t, vdevice,      Int, Long);
+        C2P(blkif_be_vbd_shrink_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED):
+        C2P(blkif_be_driver_status_changed_t, status, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
+        C2P(netif_fe_interface_status_changed_t, handle, Int, Long);
+        C2P(netif_fe_interface_status_changed_t, status, Int, Long);
+        C2P(netif_fe_interface_status_changed_t, evtchn, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+        C2P(netif_fe_driver_status_changed_t, status,        Int, Long);
+        C2P(netif_fe_driver_status_changed_t, nr_interfaces, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
+        C2P(netif_fe_interface_connect_t, handle,         Int, Long);
+        C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
+        C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
+        C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
+        C2P(netif_be_create_t, domid,        Int, Long);
+        C2P(netif_be_create_t, netif_handle, Int, Long);
+        C2P(netif_be_create_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
+        C2P(netif_be_destroy_t, domid,        Int, Long);
+        C2P(netif_be_destroy_t, netif_handle, Int, Long);
+        C2P(netif_be_destroy_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
+        C2P(netif_be_connect_t, domid,          Int, Long);
+        C2P(netif_be_connect_t, netif_handle,   Int, Long);
+        C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
+        C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
+        C2P(netif_be_connect_t, evtchn,         Int, Long);
+        C2P(netif_be_connect_t, status,         Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
+        C2P(netif_be_disconnect_t, domid,        Int, Long);
+        C2P(netif_be_disconnect_t, netif_handle, Int, Long);
+        C2P(netif_be_disconnect_t, status,       Int, Long);
+        return dict;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED):
+        C2P(netif_be_driver_status_changed_t, status, Int, Long);
+        return dict;
+    }
+
+    return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
+}
+
+static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum = (xu_message_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    return Py_BuildValue("{s:i,s:i,s:i}",
+                         "type",    xum->msg.type,
+                         "subtype", xum->msg.subtype,
+                         "id",      xum->msg.id);
+}
+
+static PyMethodDef xu_message_methods[] = {
+    { "append_payload", 
+      (PyCFunction)xu_message_append_payload,
+      METH_VARARGS,
+      "Append @str to the message payload.\n" },
+
+    { "set_response_fields",
+      (PyCFunction)xu_message_set_response_fields,
+      METH_VARARGS,
+      "Fill in the response fields in a message that was passed to us.\n" },
+
+    { "get_payload",
+      (PyCFunction)xu_message_get_payload,
+      METH_VARARGS,
+      "Return the message payload in string form.\n" },
+
+    { "get_header",
+      (PyCFunction)xu_message_get_header,
+      METH_VARARGS,
+      "Returns a dictionary of values for @type, @subtype, and @id.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_message_type;
+
+static PyObject *xu_message_new(PyObject *self, PyObject *args)
+{
+    xu_message_object *xum;
+    int type, subtype, id, dict_items_parsed = 0;
+    PyObject *payload = NULL;
+
+    if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
+        return NULL;
+
+    xum = PyObject_New(xu_message_object, &xu_message_type);
+
+    xum->msg.type    = type;
+    xum->msg.subtype = subtype;
+    xum->msg.id      = id;
+    xum->msg.length  = 0;
+
+    if ( payload == NULL )
+        return (PyObject *)xum;
+
+    if ( !PyDict_Check(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
+        PyObject_Del((PyObject *)xum);
+        return NULL;
+    }
+
+    switch ( TYPE(type, subtype) )
+    {
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
+        P2C(blkif_fe_interface_status_changed_t, handle, u32);
+        P2C(blkif_fe_interface_status_changed_t, status, u32);
+        P2C(blkif_fe_interface_status_changed_t, evtchn, u16);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
+        P2C(blkif_be_create_t, domid,        u32);
+        P2C(blkif_be_create_t, blkif_handle, u32);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
+        P2C(blkif_be_destroy_t, domid,        u32);
+        P2C(blkif_be_destroy_t, blkif_handle, u32);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
+        P2C(blkif_be_connect_t, domid,        u32);
+        P2C(blkif_be_connect_t, blkif_handle, u32);
+        P2C(blkif_be_connect_t, shmem_frame,  memory_t);
+        P2C(blkif_be_connect_t, evtchn,       u16);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
+        P2C(blkif_be_disconnect_t, domid,        u32);
+        P2C(blkif_be_disconnect_t, blkif_handle, u32);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
+        P2C(blkif_be_vbd_create_t, domid,        u32);
+        P2C(blkif_be_vbd_create_t, blkif_handle, u32);
+        P2C(blkif_be_vbd_create_t, vdevice,      blkif_vdev_t);
+        P2C(blkif_be_vbd_create_t, readonly,     u16);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
+        P2C(blkif_be_vbd_destroy_t, domid,        u32);
+        P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
+        P2C(blkif_be_vbd_destroy_t, vdevice,      blkif_vdev_t);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
+        P2C(blkif_be_vbd_grow_t, domid,                u32);
+        P2C(blkif_be_vbd_grow_t, blkif_handle,         u32);
+        P2C(blkif_be_vbd_grow_t, vdevice,              blkif_vdev_t);
+        P2C(blkif_be_vbd_grow_t, extent.sector_start,  blkif_sector_t);
+        P2C(blkif_be_vbd_grow_t, extent.sector_length, blkif_sector_t);
+        P2C(blkif_be_vbd_grow_t, extent.device,        blkif_pdev_t);
+        break;
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
+        P2C(blkif_be_vbd_shrink_t, domid,        u32);
+        P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
+        P2C(blkif_be_vbd_shrink_t, vdevice,      blkif_vdev_t);
+        break;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
+        P2C(netif_fe_interface_status_changed_t, handle, u32);
+        P2C(netif_fe_interface_status_changed_t, status, u32);
+        P2C(netif_fe_interface_status_changed_t, evtchn, u16);
+        P2C(netif_fe_interface_status_changed_t, mac[0], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[1], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[2], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[3], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[4], u8);
+        P2C(netif_fe_interface_status_changed_t, mac[5], u8);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
+        P2C(netif_be_create_t, domid,        u32);
+        P2C(netif_be_create_t, netif_handle, u32);
+        P2C(netif_be_create_t, mac[0],       u8);
+        P2C(netif_be_create_t, mac[1],       u8);
+        P2C(netif_be_create_t, mac[2],       u8);
+        P2C(netif_be_create_t, mac[3],       u8);
+        P2C(netif_be_create_t, mac[4],       u8);
+        P2C(netif_be_create_t, mac[5],       u8);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
+        P2C(netif_be_destroy_t, domid,        u32);
+        P2C(netif_be_destroy_t, netif_handle, u32);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
+        P2C(netif_be_connect_t, domid,          u32);
+        P2C(netif_be_connect_t, netif_handle,   u32);
+        P2C(netif_be_connect_t, tx_shmem_frame, memory_t);
+        P2C(netif_be_connect_t, rx_shmem_frame, memory_t);
+        P2C(netif_be_connect_t, evtchn,         u16);
+        break;
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
+        P2C(netif_be_disconnect_t, domid,        u32);
+        P2C(netif_be_disconnect_t, netif_handle, u32);
+        break;
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
+        P2C(netif_fe_driver_status_changed_t, status,        u32);
+        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+        break;
+    }
+
+    if ( dict_items_parsed != PyDict_Size(payload) )
+    {
+        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
+        PyObject_Del((PyObject *)xum);
+        return NULL;
+    }
+
+    return (PyObject *)xum;
+}
+
+static PyObject *xu_message_getattr(PyObject *obj, char *name)
+{
+    xu_message_object *xum;
+    if ( strcmp(name, "MAX_PAYLOAD") == 0 )
+        return PyInt_FromLong(sizeof(xum->msg.msg));
+    return Py_FindMethod(xu_message_methods, obj, name);
+}
+
+static void xu_message_dealloc(PyObject *self)
+{
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_message_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "message",
+    sizeof(xu_message_object),
+    0,
+    xu_message_dealloc,   /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_message_getattr,   /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** PORT ***********************
+ */
+
+static control_if_t *map_control_interface(int fd, unsigned long pfn)
+{
+    char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
+                       MAP_SHARED, fd, pfn * PAGE_SIZE);
+    if ( vaddr == MAP_FAILED )
+        return NULL;
+    return (control_if_t *)(vaddr + 2048);
+}
+static void unmap_control_interface(int fd, control_if_t *c)
+{
+    char *vaddr = (char *)c - 2048;
+    (void)munmap(vaddr, PAGE_SIZE);
+}
+
+typedef struct xu_port_object {
+    PyObject_HEAD;
+    int mem_fd;
+    int xc_handle;
+    u32 remote_dom;
+    int local_port, remote_port;
+    control_if_t    *interface;
+    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
+    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
+} xu_port_object;
+
+static PyObject *port_error;
+
+static int xup_connect(xu_port_object *xup, domid_t dom,
+                       int local_port, int remote_port){
+    // From our prespective rx = producer, tx = consumer.
+    int err = 0;
+    printf("%s> dom=%u %d:%d\n", __FUNCTION__, (unsigned int)dom, 
+           local_port, remote_port);
+
+    // Consumer = tx.
+    //xup->interface->tx_resp_prod = 0;
+    //xup->interface->tx_req_prod = 0;
+    xup->tx_resp_prod = xup->interface->tx_resp_prod;
+    xup->tx_req_cons = xup->interface->tx_resp_prod;
+    printf("%s> tx: %u %u : %u %u\n", __FUNCTION__,
+           (unsigned int)xup->interface->tx_resp_prod,
+           (unsigned int)xup->tx_resp_prod,
+           (unsigned int)xup->tx_req_cons,
+           (unsigned int)xup->interface->tx_req_prod);
+
+    // Producer = rx.
+    //xup->interface->rx_req_prod  = 0;
+    //xup->interface->rx_resp_prod = 0;
+    xup->rx_req_prod  = xup->interface->rx_req_prod;
+    xup->rx_resp_cons = xup->interface->rx_resp_prod;
+    printf("%s> rx: %u %u : %u %u\n", __FUNCTION__,
+           (unsigned int)xup->rx_resp_cons,
+           (unsigned int)xup->interface->rx_resp_prod,
+           (unsigned int)xup->interface->rx_req_prod,
+           (unsigned int)xup->rx_req_prod);
+
+    xup->remote_dom   = dom;
+    xup->local_port   = local_port;
+    xup->remote_port  = remote_port;
+
+    printf("%s< err=%d\n", __FUNCTION__, err);
+    return err;
+}
+
+static PyObject *xu_port_notify(PyObject *self, PyObject *args)
+{
+    xu_port_object *xup = (xu_port_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   c = xup->tx_req_cons;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->tx_req_prod) || 
+         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
+    {
+        PyErr_SetString(port_error, "no request to read");
+        return NULL;
+    }
+
+    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
+    xum = PyObject_New(xu_message_object, &xu_message_type);
+    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
+    if ( xum->msg.length > sizeof(xum->msg.msg) )
+        xum->msg.length = sizeof(xum->msg.msg);
+    xup->tx_req_cons++;
+    return (PyObject *)xum;
+}
+
+static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   p = xup->rx_req_prod;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
+        return NULL;
+
+    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
+    {
+        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
+        return NULL;        
+    }
+
+    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
+    {
+        PyErr_SetString(port_error, "no space to write request");
+        return NULL;
+    }
+
+    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
+    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
+
+    xup->rx_req_prod = cif->rx_req_prod = p + 1;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   c = xup->rx_resp_cons;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
+    {
+        PyErr_SetString(port_error, "no response to read");
+        return NULL;
+    }
+
+    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
+    xum = PyObject_New(xu_message_object, &xu_message_type);
+    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
+    if ( xum->msg.length > sizeof(xum->msg.msg) )
+        xum->msg.length = sizeof(xum->msg.msg);
+    xup->rx_resp_cons++;
+    return (PyObject *)xum;
+}
+
+static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    xu_message_object *xum;
+    CONTROL_RING_IDX   p = xup->tx_resp_prod;
+    control_if_t      *cif = xup->interface;
+    control_msg_t     *cmsg;
+
+    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
+        return NULL;
+
+    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
+    {
+        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
+        return NULL;        
+    }
+
+    if ( p == xup->tx_req_cons )
+    {
+        PyErr_SetString(port_error, "no space to write response");
+        return NULL;
+    }
+
+    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
+    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
+
+    xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   c = xup->tx_req_cons;
+    control_if_t      *cif = xup->interface;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->tx_req_prod) || 
+         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   p = xup->rx_req_prod;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   c = xup->rx_resp_cons;
+    control_if_t      *cif = xup->interface;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_space_to_write_response(
+    PyObject *self, PyObject *args)
+{
+    xu_port_object    *xup = (xu_port_object *)self;
+    CONTROL_RING_IDX   p = xup->tx_resp_prod;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( p == xup->tx_req_cons )
+        return PyInt_FromLong(0);
+
+    return PyInt_FromLong(1);
+}
+
+static PyMethodDef xu_port_methods[] = {
+    { "notify",
+      (PyCFunction)xu_port_notify,
+      METH_VARARGS,
+      "Send a notification to the remote end.\n" },
+
+    { "read_request",
+      (PyCFunction)xu_port_read_request,
+      METH_VARARGS,
+      "Read a request message from the control interface.\n" },
+
+    { "write_request",
+      (PyCFunction)xu_port_write_request,
+      METH_VARARGS,
+      "Write a request message to the control interface.\n" },
+
+    { "read_response",
+      (PyCFunction)xu_port_read_response,
+      METH_VARARGS,
+      "Read a response message from the control interface.\n" },
+
+    { "write_response",
+      (PyCFunction)xu_port_write_response,
+      METH_VARARGS,
+      "Write a response message to the control interface.\n" },
+
+    { "request_to_read",
+      (PyCFunction)xu_port_request_to_read,
+      METH_VARARGS,
+      "Returns TRUE if there is a request message to read.\n" },
+
+    { "space_to_write_request",
+      (PyCFunction)xu_port_space_to_write_request,
+      METH_VARARGS,
+      "Returns TRUE if there is space to write a request message.\n" },
+
+    { "response_to_read",
+      (PyCFunction)xu_port_response_to_read,
+      METH_VARARGS,
+      "Returns TRUE if there is a response message to read.\n" },
+
+    { "space_to_write_response",
+      (PyCFunction)xu_port_space_to_write_response,
+      METH_VARARGS,
+      "Returns TRUE if there is space to write a response message.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_port_type;
+
+static PyObject *xu_port_new(PyObject *self, PyObject *args)
+{
+    xu_port_object *xup;
+    u32 dom;
+    int port1, port2;
+    xc_dominfo_t info;
+
+    if ( !PyArg_ParseTuple(args, "i", &dom) )
+        return NULL;
+
+    xup = PyObject_New(xu_port_object, &xu_port_type);
+
+    if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 )
+    {
+        PyErr_SetString(port_error, "Could not open '/dev/mem'");
+        goto fail1;
+    }
+
+    /* Set the General-Purpose Subject whose page frame will be mapped. */
+    (void)ioctl(xup->mem_fd, _IO('M', 1), (unsigned long)dom);
+
+    if ( (xup->xc_handle = xc_interface_open()) == -1 )
+    {
+        PyErr_SetString(port_error, "Could not open Xen control interface");
+        goto fail2;
+    }
+
+    if ( dom == 0 )
+    {
+        /*
+         * The control-interface event channel for DOM0 is already set up.
+         * We use an ioctl to discover the port at our end of the channel.
+         */
+        port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
+        port2 = -1; /* We don't need the remote end of the DOM0 link. */
+        if ( port1 < 0 )
+        {
+            PyErr_SetString(port_error, "Could not open channel to DOM0");
+            goto fail3;
+        }
+    }
+    else if ( xc_evtchn_bind_interdomain(xup->xc_handle, 
+                                         DOMID_SELF, dom, 
+                                         &port1, &port2) != 0 )
+    {
+        PyErr_SetString(port_error, "Could not open channel to domain");
+        goto fail3;
+    }
+
+    if ( (xc_domain_getinfo(xup->xc_handle, dom, 1, &info) != 1) ||
+         (info.domid != dom) )
+    {
+        PyErr_SetString(port_error, "Failed to obtain domain status");
+        goto fail4;
+    }
+
+    xup->interface = 
+        map_control_interface(xup->mem_fd, info.shared_info_frame);
+    if ( xup->interface == NULL )
+    {
+        PyErr_SetString(port_error, "Failed to map domain control interface");
+        goto fail4;
+    }
+
+    xup_connect(xup, dom, port1, port2);
+    return (PyObject *)xup;
+
+    
+ fail4:
+    (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
+ fail3:
+    (void)xc_interface_close(xup->xc_handle);
+ fail2:
+    (void)close(xup->mem_fd);
+ fail1:
+    PyObject_Del((PyObject *)xup);
+    return NULL;        
+}
+
+static PyObject *xu_port_getattr(PyObject *obj, char *name)
+{
+    xu_port_object *xup = (xu_port_object *)obj;
+    if ( strcmp(name, "local_port") == 0 )
+        return PyInt_FromLong(xup->local_port);
+    if ( strcmp(name, "remote_port") == 0 )
+        return PyInt_FromLong(xup->remote_port);
+    if ( strcmp(name, "remote_dom") == 0 )
+        return PyInt_FromLong(xup->remote_dom);
+    return Py_FindMethod(xu_port_methods, obj, name);
+}
+
+static void xu_port_dealloc(PyObject *self)
+{
+    xu_port_object *xup = (xu_port_object *)self;
+    unmap_control_interface(xup->mem_fd, xup->interface);
+    if ( xup->remote_dom != 0 )
+        (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
+    (void)xc_interface_close(xup->xc_handle);
+    (void)close(xup->mem_fd);
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_port_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "port",
+    sizeof(xu_port_object),
+    0,
+    xu_port_dealloc,     /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_port_getattr,     /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** BUFFER ***********************
+ */
+
+#define BUFSZ 65536
+#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
+typedef unsigned int BUF_IDX;
+
+typedef struct {
+    PyObject_HEAD;
+    char        *buf;
+    unsigned int prod, cons;
+} xu_buffer_object;
+
+static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
+{
+    PyObject *str1, *str2;
+    int len1, len2, c = MASK_BUF_IDX(xub->cons);
+
+    len1 = xub->prod - xub->cons;
+    if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
+        len1 = BUFSZ - c;
+    if ( len1 > max )         /* clip to specified maximum */
+        len1 = max;
+    if ( len1 < 0 )           /* sanity */
+        len1 = 0;
+
+    if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
+        return NULL;
+
+    if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
+    {
+        len2 = max - len1;
+        if ( len2 > MASK_BUF_IDX(xub->prod) )
+            len2 = MASK_BUF_IDX(xub->prod);
+        if ( len2 > 0 )
+        {
+            str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
+            if ( str2 == NULL )
+                return NULL;
+            PyString_ConcatAndDel(&str1, str2);
+            if ( str1 == NULL )
+                return NULL;
+        }
+    }
+
+    return str1;
+}
+
+static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    int max = 1024;
+
+    if ( !PyArg_ParseTuple(args, "|i", &max) )
+        return NULL;
+    
+    return __xu_buffer_peek(xub, max);
+}
+
+static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    PyObject *str;
+    int max = 1024;
+
+    if ( !PyArg_ParseTuple(args, "|i", &max) )
+        return NULL;
+
+    if ( (str = __xu_buffer_peek(xub, max)) != NULL )
+        xub->cons += PyString_Size(str);
+
+    return str;
+}
+
+static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    int max, len;
+
+    if ( !PyArg_ParseTuple(args, "i", &max) )
+        return NULL;
+
+    len = xub->prod - xub->cons;
+    if ( len > max )
+        len = max;
+    if ( len < 0 )
+        len = 0;
+
+    xub->cons += len;
+
+    return PyInt_FromLong(len);
+}
+
+static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    char *str;
+    int len, len1, len2;
+
+    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
+        return NULL;
+
+    len1 = len;
+    if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
+        len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
+    if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
+        len1 = BUFSZ - (xub->prod - xub->cons);
+
+    if ( len1 == 0 )
+        return PyInt_FromLong(0);
+
+    memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
+    xub->prod += len1;
+
+    if ( len1 < len )
+    {
+        len2 = len - len1;
+        if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
+            len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
+        if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
+            len2 = BUFSZ - (xub->prod - xub->cons);
+        if ( len2 != 0 )
+        {
+            memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
+            xub->prod += len2;
+            return PyInt_FromLong(len1 + len2);
+        }
+    }
+
+    return PyInt_FromLong(len1);
+}
+
+static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( xub->cons == xub->prod )
+        return PyInt_FromLong(1);
+
+    return PyInt_FromLong(0);
+}
+
+static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    if ( (xub->prod - xub->cons) == BUFSZ )
+        return PyInt_FromLong(1);
+
+    return PyInt_FromLong(0);
+}
+
+static PyMethodDef xu_buffer_methods[] = {
+    { "peek", 
+      (PyCFunction)xu_buffer_peek,
+      METH_VARARGS,
+      "Peek up to @max bytes from the buffer. Returns a string.\n" },
+
+    { "read", 
+      (PyCFunction)xu_buffer_read,
+      METH_VARARGS,
+      "Read up to @max bytes from the buffer. Returns a string.\n" },
+
+    { "discard", 
+      (PyCFunction)xu_buffer_discard,
+      METH_VARARGS,
+      "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
+
+    { "write", 
+      (PyCFunction)xu_buffer_write,
+      METH_VARARGS,
+      "Write @string into buffer. Return number of bytes written.\n" },
+
+    { "empty", 
+      (PyCFunction)xu_buffer_empty,
+      METH_VARARGS,
+      "Return TRUE if the buffer is empty.\n" },
+
+    { "full", 
+      (PyCFunction)xu_buffer_full,
+      METH_VARARGS,
+      "Return TRUE if the buffer is full.\n" },
+
+    { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_buffer_type;
+
+static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
+{
+    xu_buffer_object *xub;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
+
+    if ( (xub->buf = malloc(BUFSZ)) == NULL )
+    {
+        PyObject_Del((PyObject *)xub);
+        return NULL;
+    }
+
+    xub->prod = xub->cons = 0;
+
+    return (PyObject *)xub;
+}
+
+static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
+{
+    return Py_FindMethod(xu_buffer_methods, obj, name);
+}
+
+static void xu_buffer_dealloc(PyObject *self)
+{
+    xu_buffer_object *xub = (xu_buffer_object *)self;
+    free(xub->buf);
+    PyObject_Del(self);
+}
+
+static PyTypeObject xu_buffer_type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "buffer",
+    sizeof(xu_buffer_object),
+    0,
+    xu_buffer_dealloc,   /* tp_dealloc     */
+    NULL,                /* tp_print       */
+    xu_buffer_getattr,   /* tp_getattr     */
+    NULL,                /* tp_setattr     */
+    NULL,                /* tp_compare     */
+    NULL,                /* tp_repr        */
+    NULL,                /* tp_as_number   */
+    NULL,                /* tp_as_sequence */
+    NULL,                /* tp_as_mapping  */
+    NULL                 /* tp_hash        */
+};
+
+
+
+/*
+ * *********************** MODULE WRAPPER ***********************
+ */
+
+static void handle_child_death(int dummy)
+{
+    while ( waitpid(-1, NULL, WNOHANG) > 0 )
+        continue;
+}
+
+static PyObject *xu_autoreap(PyObject *self, PyObject *args)
+{
+    struct sigaction sa;
+
+    if ( !PyArg_ParseTuple(args, "") )
+        return NULL;
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_handler = handle_child_death;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+    (void)sigaction(SIGCHLD, &sa, NULL);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMethodDef xu_methods[] = {
+    { "notifier", xu_notifier_new, METH_VARARGS, 
+      "Create a new notifier." },
+    { "message", xu_message_new, METH_VARARGS, 
+      "Create a new communications message." },
+    { "port", xu_port_new, METH_VARARGS, 
+      "Create a new communications port." },
+    { "buffer", xu_buffer_new, METH_VARARGS, 
+      "Create a new ring buffer." },
+    { "autoreap", xu_autoreap, METH_VARARGS,
+      "Ensure that zombie children are automatically reaped by the OS." },
+    { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC initxu(void)
+{
+    PyObject *m, *d;
+
+    m = Py_InitModule(XENPKG, xu_methods);
+
+    d = PyModule_GetDict(m);
+    port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
+    PyDict_SetItemString(d, "PortError", port_error);
+}
diff --git a/tools/python/xen/util/Brctl.py b/tools/python/xen/util/Brctl.py
new file mode 100644 (file)
index 0000000..9d3eba1
--- /dev/null
@@ -0,0 +1,160 @@
+"""Bridge control utilities.
+"""
+import os
+import os.path
+import re
+import sys
+
+os.defpath = os.defpath + ':/sbin:/usr/sbin:/usr/local/sbin'
+CMD_IFCONFIG = 'ifconfig'
+CMD_ROUTE    = 'route'
+CMD_BRCTL    = 'brctl'
+CMD_IPTABLES = "iptables"
+
+opts = None
+
+class Opts:
+
+    def __init__(self, defaults):
+        for (k, v) in defaults.items():
+            setattr(self, k, v)
+        pass
+
+def cmd(p, s):
+    """Print and execute command 'p' with args 's'.
+    """
+    global opts
+    c = p + ' ' + s
+    if opts.verbose: print c
+    if not opts.dryrun:
+        os.system(c)
+
+def vif_bridge_add(params):
+    """Add the network interface for vif on dom to a bridge.
+    """
+    cmd(CMD_BRCTL, 'addif %(bridge)s %(vif)s' % params)
+
+def vif_bridge_rem(params):
+    """Remove the network interface for vif on dom from a bridge.
+    """
+    cmd(CMD_BRCTL, 'delif %(bridge)s %(vif)s' % params)
+
+def vif_restrict_addr(vif, addr, delete=0):
+    d = { 'vif': vif, 'addr': addr}
+    if delete:
+        d['flag'] = '-D'
+    else:
+        d['flag'] = '-A'
+    cmd(CMD_IPTABLES, '-P FORWARD DROP')
+    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-in %(vif)s -s %(addr)s -j ACCEPT' % d)
+    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-out %(vif)s -d %(addr)s -j ACCEPT' % d)
+
+def bridge_create(bridge, **kwd):
+    """Create a bridge.
+    Defaults hello time to 0, forward delay to 0 and stp off.
+    """
+    cmd(CMD_BRCTL, 'addbr %s' % bridge)
+    if kwd.get('hello', None) is None:
+        kwd['hello'] = 0
+    if kwd.get('fd', None) is None:
+        kwd['fd'] = 0
+    if kwd.get('stp', None) is None:
+        kwd['stp'] = 'off'
+    bridge_set(bridge, **kwd)
+
+def bridge_set(bridge, hello=None, fd=None, stp=None):
+    """Set bridge parameters.
+    """
+    if hello is not None:
+        cmd(CMD_BRCTL, 'sethello %s %d' % (bridge, hello))
+    if fd is not None:
+        cmd(CMD_BRCTL, 'setfd %s %d' % (bridge, fd))
+    if stp is not None:
+        cmd(CMD_BRCTL, 'stp %s %s' % (bridge, stp))
+
+def bridge_del(bridge):
+    """Delete a bridge.
+    """
+    cmd(CMD_BRCTL, 'delbr %s' % bridge)
+
+def routes():
+    """Return a list of the routes.
+    """
+    fin = os.popen(CMD_ROUTE + ' -n', 'r')
+    routes = []
+    for x in fin:
+        if x.startswith('Kernel'): continue
+        if x.startswith('Destination'): continue
+        x = x.strip()
+        y = x.split()
+        z = { 'destination': y[0],
+              'gateway'    : y[1],
+              'mask'       : y[2],
+              'flags'      : y[3],
+              'metric'     : y[4],
+              'ref'        : y[5],
+              'use'        : y[6],
+              'interface'  : y[7] }
+        routes.append(z)
+    return routes
+
+def ifconfig(interface):
+    """Return the ip config for an interface,
+    """
+    fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r')
+    inetre = re.compile('\s*inet\s*addr:(?P<address>\S*)\s*Bcast:(?P<broadcast>\S*)\s*Mask:(?P<mask>\S*)')
+    info = None
+    for x in fin:
+        m = inetre.match(x)
+        if not m: continue
+        info = m.groupdict()
+        info['interface'] = interface
+        break
+    return info
+
+def reconfigure(interface, bridge):
+    """Reconfigure an interface to be attached to a bridge, and give the bridge
+    the IP address etc. from interface. Move the default route to the interface
+    to the bridge.
+
+    """
+    global opts
+    intf_info = ifconfig(interface)
+    if not intf_info:
+        print >>sys.stderr, 'Interface not found:', interface
+        return
+    #bridge_info = ifconfig(bridge)
+    #if not bridge_info:
+    #    print >>sys.stderr, 'Bridge not found:', bridge
+    #    return
+    route_info = routes()
+    intf_info['bridge'] = bridge
+    intf_info['gateway'] = None
+    for r in route_info:
+        if (r['destination'] == '0.0.0.0' and
+            'G' in r['flags'] and
+            r['interface'] == interface):
+            intf_info['gateway'] = r['gateway']
+    if not intf_info['gateway']:
+        print >>sys.stderr, 'Gateway not found: ', interface
+        return
+    cmd(CMD_IFCONFIG,
+        '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up'
+        % intf_info)
+    cmd(CMD_ROUTE,
+        'add default gateway %(gateway)s dev %(bridge)s'
+        % intf_info)
+    cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info)
+    cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info)
+
+defaults = {
+    'verbose'  : 1,
+    'dryrun'   : 0,
+    }
+
+opts = Opts(defaults)
+
+def set_opts(val):
+    global opts
+    opts = val
+    return opts
diff --git a/tools/python/xen/util/__init__.py b/tools/python/xen/util/__init__.py
new file mode 100644 (file)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/tools/python/xen/util/console_client.py b/tools/python/xen/util/console_client.py
new file mode 100644 (file)
index 0000000..7ac63ae
--- /dev/null
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+
+##############################################
+# Console client for Xen guest OSes
+# Copyright (c) 2004, K A Fraser
+##############################################
+
+import errno, os, signal, socket, struct, sys
+
+from termios import *
+# Indexes into termios.tcgetattr() list.
+IFLAG  = 0
+OFLAG  = 1
+CFLAG  = 2
+LFLAG  = 3
+ISPEED = 4
+OSPEED = 5
+CC     = 6
+
+def __child_death(signum, frame):
+    global stop
+    stop = True
+
+def __recv_from_sock(sock):
+    global stop
+    stop = False
+    while not stop:
+        try:
+            data = sock.recv(1024)
+            os.write(1, data)
+        except socket.error, error:
+            if error[0] != errno.EINTR:
+                raise
+    os.wait()
+
+def __send_to_sock(sock):
+    while 1:
+        data = os.read(0,1024)
+        if ord(data[0]) == ord(']')-64:
+            break
+        try:
+            sock.send(data)
+        except socket.error, error:
+            if error[0] == errno.EPIPE:
+                sys.exit(0)
+            if error[0] != errno.EINTR:
+                raise
+    sys.exit(0)
+
+def connect(host,port):
+    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+    sock.connect((host,port))
+
+    oattrs = tcgetattr(0)
+    nattrs = tcgetattr(0)
+    nattrs[IFLAG] = nattrs[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
+    nattrs[OFLAG] = nattrs[OFLAG] & ~(OPOST)
+    nattrs[CFLAG] = nattrs[CFLAG] & ~(CSIZE | PARENB)
+    nattrs[CFLAG] = nattrs[CFLAG] | CS8
+    nattrs[LFLAG] = nattrs[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
+    nattrs[CC][VMIN] = 1
+    nattrs[CC][VTIME] = 0
+
+    if os.fork():
+        signal.signal(signal.SIGCHLD, __child_death)
+        print "************ REMOTE CONSOLE: CTRL-] TO QUIT ********"
+        tcsetattr(0, TCSAFLUSH, nattrs)
+        try:
+            __recv_from_sock(sock)
+        finally:
+            tcsetattr(0, TCSAFLUSH, oattrs)
+            print
+            print "************ REMOTE CONSOLE EXITED *****************"
+    else:
+        signal.signal(signal.SIGPIPE, signal.SIG_IGN)
+        __send_to_sock(sock)
+
+if __name__ == '__main__':
+    if len(sys.argv) != 3:
+        print sys.argv[0] + " <host> <port>"
+        sys.exit(1)
+    connect(str(sys.argv[1]),int(sys.argv[2]))
diff --git a/tools/python/xen/util/ip.py b/tools/python/xen/util/ip.py
new file mode 100644 (file)
index 0000000..8396e0d
--- /dev/null
@@ -0,0 +1,113 @@
+import os
+import re
+import socket
+import struct
+
+def readlines(fd):
+    """Version of readlines safe against EINTR.
+    """
+    import errno
+    
+    lines = []
+    while 1:
+        try:
+            line = fd.readline()
+        except IOError, ex:
+            if ex.errno == errno.EINTR:
+                continue
+            else:
+                raise
+        if line == '': break
+        lines.append(line)
+    return lines
+
+def readline(fd):
+    """Version of readline safe against EINTR.
+    """
+    while 1:
+        try:
+            return fd.readline()
+        except IOError, ex:
+            if ex.errno == errno.EINTR:
+                continue
+            else:
+                raise
+
+##### Networking-related functions
+
+"""Bridge for network backend.
+When bridging is used, eth0 may not have an IP address,
+as it may have been moved onto the bridge.
+"""
+NBE_BRIDGE = 'nbe-br'
+
+def get_current_ipaddr(dev='eth0'):
+    """Return a string containing the primary IP address for the given
+    network interface (default 'eth0').
+    """
+    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
+    lines = readlines(fd)
+    for line in lines:
+        m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
+                       line )
+        if m:
+            return m.group(1)
+    if dev == 'eth0':
+        return get_current_ipaddr(NBE_BRIDGE)
+    return None
+
+def get_current_ipmask(dev='eth0'):
+    """Return a string containing the primary IP netmask for the given
+    network interface (default 'eth0').
+    """
+    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
+    lines = readlines(fd)
+    for line in lines:
+        m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
+                       line )
+        if m:
+            return m.group(1)
+    if dev == 'eth0':
+        return get_current_ipmask(NBE_BRIDGE)
+    return None
+
+def get_current_ipgw(dev='eth0'):
+    """Return a string containing the IP gateway for the given
+    network interface (default 'eth0').
+    """
+    fd = os.popen( '/sbin/route -n' )
+    lines = readlines(fd)
+    for line in lines:
+        m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
+                       '\s+\S+\s+\S*G.*' + dev + '.*', line )
+        if m:
+            return m.group(1)
+    if dev == 'eth0':
+        return get_current_ipgw(NBE_BRIDGE)
+    return None
+
+def inet_aton(addr):
+    """Convert an IP addr in IPv4 dot notation into an int.
+    """
+    b = socket.inet_aton(addr)
+    return struct.unpack('!I', b)[0]
+
+def inet_ntoa(n):
+    """Convert an int into an IP addr in IPv4 dot notation.
+    """
+    b = struct.pack('!I', n)
+    return socket.inet_ntoa(b)
+
+def add_offset_to_ip(addr, offset):
+    """Add a numerical offset to an IP addr in IPv4 dot notation.
+    """
+    n = inet_aton(addr)
+    n += offset
+    return inet_ntoa(n)
+
+def check_subnet( ip, network, netmask ):
+    n_ip = inet_aton(ip)
+    n_net = inet_aton(network)
+    n_mask = inet_aton(netmask)
+    return (n_ip & n_mask) == (n_net & n_mask)
+
diff --git a/tools/python/xen/util/tempfile.py b/tools/python/xen/util/tempfile.py
new file mode 100644 (file)
index 0000000..756d8c8
--- /dev/null
@@ -0,0 +1,451 @@
+"""Temporary files.
+
+This module provides generic, low- and high-level interfaces for
+creating temporary files and directories.  The interfaces listed
+as "safe" just below can be used without fear of race conditions.
+Those listed as "unsafe" cannot, and are provided for backward
+compatibility only.
+
+This module also provides some data items to the user:
+
+  TMP_MAX  - maximum number of names that will be tried before
+             giving up.
+  template - the default prefix for all temporary names.
+             You may change this to control the default prefix.
+  tempdir  - If this is set to a string before the first use of
+             any routine from this module, it will be considered as
+             another candidate location to store temporary files.
+"""
+
+__all__ = [
+    "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
+    "mkstemp", "mkdtemp",                  # low level safe interfaces
+    "mktemp",                              # deprecated unsafe interface
+    "TMP_MAX", "gettempprefix",            # constants
+    "tempdir", "gettempdir"
+   ]
+
+
+# Imports.
+
+import os as _os
+import errno as _errno
+from random import Random as _Random
+
+if _os.name == 'mac':
+    import Carbon.Folder as _Folder
+    import Carbon.Folders as _Folders
+
+try:
+    import fcntl as _fcntl
+    # If PYTHONCASEOK is set on Windows, stinking FCNTL.py gets
+    # imported, and we don't get an ImportError then.  Provoke
+    # an AttributeError instead in that case.
+    _fcntl.fcntl
+except (ImportError, AttributeError):
+    def _set_cloexec(fd):
+        pass
+else:
+    def _set_cloexec(fd):
+        flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
+        if flags >= 0:
+            # flags read successfully, modify
+            flags |= _fcntl.FD_CLOEXEC
+            _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
+
+
+try:
+    import thread as _thread
+except ImportError:
+    import dummy_thread as _thread
+_allocate_lock = _thread.allocate_lock
+
+_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
+if hasattr(_os, 'O_NOINHERIT'):
+    _text_openflags |= _os.O_NOINHERIT
+if hasattr(_os, 'O_NOFOLLOW'):
+    _text_openflags |= _os.O_NOFOLLOW
+
+_bin_openflags = _text_openflags
+if hasattr(_os, 'O_BINARY'):
+    _bin_openflags |= _os.O_BINARY
+
+if hasattr(_os, 'TMP_MAX'):
+    TMP_MAX = _os.TMP_MAX
+else:
+    TMP_MAX = 10000
+
+template = "tmp"
+
+tempdir = None
+
+# Internal routines.
+
+_once_lock = _allocate_lock()
+
+class _RandomNameSequence:
+    """An instance of _RandomNameSequence generates an endless
+    sequence of unpredictable strings which can safely be incorporated
+    into file names.  Each string is six characters long.  Multiple
+    threads can safely use the same instance at the same time.
+
+    _RandomNameSequence is an iterator."""
+
+    characters = ("abcdefghijklmnopqrstuvwxyz" +
+                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+                  "0123456789-_")
+
+    def __init__(self):
+        self.mutex = _allocate_lock()
+        self.rng = _Random()
+        self.normcase = _os.path.normcase
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        m = self.mutex
+        c = self.characters
+        choose = self.rng.choice
+
+        m.acquire()
+        try:
+            letters = [choose(c) for dummy in "123456"]
+        finally:
+            m.release()
+
+        return self.normcase(''.join(letters))
+
+def _candidate_tempdir_list():
+    """Generate a list of candidate temporary directories which
+    _get_default_tempdir will try."""
+
+    dirlist = []
+
+    # First, try the environment.
+    for envname in 'TMPDIR', 'TEMP', 'TMP':
+        dirname = _os.getenv(envname)
+        if dirname: dirlist.append(dirname)
+
+    # Failing that, try OS-specific locations.
+    if _os.name == 'mac':
+        try:
+            fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
+                                              _Folders.kTemporaryFolderType, 1)
+            dirname = fsr.as_pathname()
+            dirlist.append(dirname)
+        except _Folder.error:
+            pass
+    elif _os.name == 'riscos':
+        dirname = _os.getenv('Wimp$ScrapDir')
+        if dirname: dirlist.append(dirname)
+    elif _os.name == 'nt':
+        dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
+    else:
+        dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
+
+    # As a last resort, the current directory.
+    try:
+        dirlist.append(_os.getcwd())
+    except (AttributeError, _os.error):
+        dirlist.append(_os.curdir)
+
+    return dirlist
+
+def _get_default_tempdir():
+    """Calculate the default directory to use for temporary files.
+    This routine should be called exactly once.
+
+    We determine whether or not a candidate temp dir is usable by
+    trying to create and write to a file in that directory.  If this
+    is successful, the test file is deleted.  To prevent denial of
+    service, the name of the test file must be randomized."""
+
+    namer = _RandomNameSequence()
+    dirlist = _candidate_tempdir_list()
+    flags = _text_openflags
+
+    for dir in dirlist:
+        if dir != _os.curdir:
+            dir = _os.path.normcase(_os.path.abspath(dir))
+        # Try only a few names per directory.
+        for seq in xrange(100):
+            name = namer.next()
+            filename = _os.path.join(dir, name)
+            try:
+                fd = _os.open(filename, flags, 0600)
+                fp = _os.fdopen(fd, 'w')
+                fp.write('blat')
+                fp.close()
+                _os.unlink(filename)
+                del fp, fd
+                return dir
+            except (OSError, IOError), e:
+                if e[0] != _errno.EEXIST:
+                    break # no point trying more names in this directory
+                pass
+    raise IOError, (_errno.ENOENT,
+                    ("No usable temporary directory found in %s" % dirlist))
+
+_name_sequence = None
+
+def _get_candidate_names():
+    """Common setup sequence for all user-callable interfaces."""
+
+    global _name_sequence
+    if _name_sequence is None:
+        _once_lock.acquire()
+        try:
+            if _name_sequence is None:
+                _name_sequence = _RandomNameSequence()
+        finally:
+            _once_lock.release()
+    return _name_sequence
+
+
+def _mkstemp_inner(dir, pre, suf, flags):
+    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
+
+    names = _get_candidate_names()
+
+    for seq in xrange(TMP_MAX):
+        name = names.next()
+        file = _os.path.join(dir, pre + name + suf)
+        try:
+            fd = _os.open(file, flags, 0600)
+            _set_cloexec(fd)
+            return (fd, file)
+        except OSError, e:
+            if e.errno == _errno.EEXIST:
+                continue # try again
+            raise
+
+    raise IOError, (_errno.EEXIST, "No usable temporary file name found")
+
+
+# User visible interfaces.
+
+def gettempprefix():
+    """Accessor for tempdir.template."""
+    return template
+
+tempdir = None
+
+def gettempdir():
+    """Accessor for tempdir.tempdir."""
+    global tempdir
+    if tempdir is None:
+        _once_lock.acquire()
+        try:
+            if tempdir is None:
+                tempdir = _get_default_tempdir()
+        finally:
+            _once_lock.release()
+    return tempdir
+
+def mkstemp(suffix="", prefix=template, dir=None, text=False):
+    """mkstemp([suffix, [prefix, [dir, [text]]]])
+    User-callable function to create and return a unique temporary
+    file.  The return value is a pair (fd, name) where fd is the
+    file descriptor returned by os.open, and name is the filename.
+
+    If 'suffix' is specified, the file name will end with that suffix,
+    otherwise there will be no suffix.
+
+    If 'prefix' is specified, the file name will begin with that prefix,
+    otherwise a default prefix is used.
+
+    If 'dir' is specified, the file will be created in that directory,
+    otherwise a default directory is used.
+
+    If 'text' is specified and true, the file is opened in text
+    mode.  Else (the default) the file is opened in binary mode.  On
+    some operating systems, this makes no difference.
+
+    The file is readable and writable only by the creating user ID.
+    If the operating system uses permission bits to indicate whether a
+    file is executable, the file is executable by no one. The file
+    descriptor is not inherited by children of this process.
+
+    Caller is responsible for deleting the file when done with it.
+    """
+
+    if dir is None:
+        dir = gettempdir()
+
+    if text:
+        flags = _text_openflags
+    else:
+        flags = _bin_openflags
+
+    return _mkstemp_inner(dir, prefix, suffix, flags)
+
+
+def mkdtemp(suffix="", prefix=template, dir=None):
+    """mkdtemp([suffix, [prefix, [dir]]])
+    User-callable function to create and return a unique temporary
+    directory.  The return value is the pathname of the directory.
+
+    Arguments are as for mkstemp, except that the 'text' argument is
+    not accepted.
+
+    The directory is readable, writable, and searchable only by the
+    creating user.
+
+    Caller is responsible for deleting the directory when done with it.
+    """
+
+    if dir is None:
+        dir = gettempdir()
+
+    names = _get_candidate_names()
+
+    for seq in xrange(TMP_MAX):
+        name = names.next()
+        file = _os.path.join(dir, prefix + name + suffix)
+        try:
+            _os.mkdir(file, 0700)
+            return file
+        except OSError, e:
+            if e.errno == _errno.EEXIST:
+                continue # try again
+            raise
+
+    raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
+
+def mktemp(suffix="", prefix=template, dir=None):
+    """mktemp([suffix, [prefix, [dir]]])
+    User-callable function to return a unique temporary file name.  The
+    file is not created.
+
+    Arguments are as for mkstemp, except that the 'text' argument is
+    not accepted.
+
+    This function is unsafe and should not be used.  The file name
+    refers to a file that did not exist at some point, but by the time
+    you get around to creating it, someone else may have beaten you to
+    the punch.
+    """
+
+##    from warnings import warn as _warn
+##    _warn("mktemp is a potential security risk to your program",
+##          RuntimeWarning, stacklevel=2)
+
+    if dir is None:
+        dir = gettempdir()
+
+    names = _get_candidate_names()
+    for seq in xrange(TMP_MAX):
+        name = names.next()
+        file = _os.path.join(dir, prefix + name + suffix)
+        if not _os.path.exists(file):
+            return file
+
+    raise IOError, (_errno.EEXIST, "No usable temporary filename found")
+
+class _TemporaryFileWrapper:
+    """Temporary file wrapper
+
+    This class provides a wrapper around files opened for
+    temporary use.  In particular, it seeks to automatically
+    remove the file when it is no longer needed.
+    """
+
+    def __init__(self, file, name):
+        self.file = file
+        self.name = name
+        self.close_called = False
+
+    def __getattr__(self, name):
+        file = self.__dict__['file']
+        a = getattr(file, name)
+        if type(a) != type(0):
+            setattr(self, name, a)
+        return a
+
+    # NT provides delete-on-close as a primitive, so we don't need
+    # the wrapper to do anything special.  We still use it so that
+    # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
+    if _os.name != 'nt':
+
+        # Cache the unlinker so we don't get spurious errors at
+        # shutdown when the module-level "os" is None'd out.  Note
+        # that this must be referenced as self.unlink, because the
+        # name TemporaryFileWrapper may also get None'd out before
+        # __del__ is called.
+        unlink = _os.unlink
+
+        def close(self):
+            if not self.close_called:
+                self.close_called = True
+                self.file.close()
+                self.unlink(self.name)
+
+        def __del__(self):
+            self.close()
+
+def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
+                       prefix=template, dir=None):
+    """Create and return a temporary file.
+    Arguments:
+    'prefix', 'suffix', 'dir' -- as for mkstemp.
+    'mode' -- the mode argument to os.fdopen (default "w+b").
+    'bufsize' -- the buffer size argument to os.fdopen (default -1).
+    The file is created as mkstemp() would do it.
+
+    Returns a file object; the name of the file is accessible as
+    file.name.  The file will be automatically deleted when it is
+    closed.
+    """
+
+    if dir is None:
+        dir = gettempdir()
+
+    if 'b' in mode:
+        flags = _bin_openflags
+    else:
+        flags = _text_openflags
+
+    # Setting O_TEMPORARY in the flags causes the OS to delete
+    # the file when it is closed.  This is only supported by Windows.
+    if _os.name == 'nt':
+        flags |= _os.O_TEMPORARY
+
+    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
+    file = _os.fdopen(fd, mode, bufsize)
+    return _TemporaryFileWrapper(file, name)
+
+if _os.name != 'posix' or _os.sys.platform == 'cygwin':
+    # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
+    # while it is open.
+    TemporaryFile = NamedTemporaryFile
+
+else:
+    def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
+                      prefix=template, dir=None):
+        """Create and return a temporary file.
+        Arguments:
+        'prefix', 'suffix', 'directory' -- as for mkstemp.
+        'mode' -- the mode argument to os.fdopen (default "w+b").
+        'bufsize' -- the buffer size argument to os.fdopen (default -1).
+        The file is created as mkstemp() would do it.
+
+        Returns a file object.  The file has no name, and will cease to
+        exist when it is closed.
+        """
+
+        if dir is None:
+            dir = gettempdir()
+
+        if 'b' in mode:
+            flags = _bin_openflags
+        else:
+            flags = _text_openflags
+
+        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
+        try:
+            _os.unlink(name)
+            return _os.fdopen(fd, mode, bufsize)
+        except:
+            _os.close(fd)
+            raise
diff --git a/tools/python/xen/xend/Args.py b/tools/python/xen/xend/Args.py
new file mode 100644 (file)
index 0000000..527e841
--- /dev/null
@@ -0,0 +1,126 @@
+import sxp
+
+class ArgError(StandardError):
+    pass
+
+class Args:
+    """Argument encoding support for HTTP.
+    """
+    
+    def __init__(self, paramspec, keyspec):
+        self.arg_ord = []
+        self.arg_dict = {}
+        self.key_ord = []
+        self.key_dict = {}
+        for (name, type) in paramspec:
+                self.arg_ord.append(name)
+                self.arg_dict[name] = type
+        for (name, type) in keyspec:
+                self.key_ord.append(name)
+                self.key_dict[name] = type
+
+    def get_args(self, d, xargs=None):
+        args = {}
+        keys = {}
+        params = []
+        if xargs:
+            self.split_args(xargs, args, keys)
+        self.split_args(d, args, keys)
+        for a in self.arg_ord:
+            if a in args:
+                params.append(args[a])
+            else:
+                raise ArgError('Missing parameter: %s' % a)
+        return (params, keys)
+
+    def split_args(self, d, args, keys):
+        for (k, v) in d.items():
+            if k in self.arg_dict:
+                type = self.arg_dict[k]
+                val = self.coerce(type, v)
+                args[k] = val
+            elif k in self.key_dict:
+                type = self.key_dict[k]
+                val = self.coerce(type, v)
+                keys[k] = val
+            else:
+                raise ArgError('Invalid parameter: %s' % k)
+
+    def get_form_args(self, f, xargs=None):
+        d = {}
+        for (k, v) in f.items():
+            n = len(v)
+            if ((k not in self.arg_dict) and
+                (k not in self.key_dict)):
+                continue
+            if n == 0:
+                continue
+            elif n == 1:
+                d[k] = v[0]
+            else:
+                raise ArgError('Too many values for %s' % k)
+        return self.get_args(d, xargs=xargs)
+
+    def coerce(self, type, v):
+        try:
+            if type == 'int':
+                return int(v)
+            if type == 'str':
+                return str(v)
+            if type == 'sxpr':
+                return self.sxpr(v)
+        except ArgError:
+            raise
+        except StandardError, ex:
+            raise ArgError(str(ex))
+
+    def sxpr(self, v):
+        if instanceof(v, types.ListType):
+            return v
+        if instanceof(v, types.File) or hasattr(v, 'readline'):
+            return sxpr_file(v)
+        if instanceof(v, types.StringType):
+            return sxpr_file(StringIO(v))
+        return str(v)
+
+    def sxpr_file(self, fin):
+        try:
+            vals = sxp.parse(fin)
+        except:
+            raise ArgError('Coercion to sxpr failed')
+        if len(vals) == 1:
+            return vals[0]
+        else:
+            raise ArgError('Too many sxprs')
+
+    def call_with_args(self, fn, args, xargs=None):
+        (params, keys) = self.get_args(args, xargs=xargs)
+        fn(*params, **keys)
+
+    def call_with_form_args(self, fn, fargs, xargs=None):
+        (params, keys) = self.get_form_args(fargs, xargs=xargs)
+        fn(*params, **keys)
+
+class ArgFn(Args):
+    """Represent a remote HTTP operation as a function.
+    Used on the client.
+    """
+
+    def __init__(self, fn, paramspec, keyspec={}):
+        Args.__init__(self, paramspec, keyspec)
+        self.fn = fn
+
+    def __call__(self, fargs, xargs=None):
+        return self.call_with_args(self.fn, fargs, xargs=xargs)
+    
+class FormFn(Args):
+    """Represent an operation as a function over a form.
+    Used in the HTTP server.
+    """
+
+    def __init__(self, fn, paramspec, keyspec={}):
+        Args.__init__(self, paramspec, keyspec)
+        self.fn = fn
+
+    def __call__(self, fargs, xargs=None):
+        return self.call_with_form_args(self.fn, fargs, xargs=xargs)
diff --git a/tools/python/xen/xend/EventServer.py b/tools/python/xen/xend/EventServer.py
new file mode 100644 (file)
index 0000000..20c567a
--- /dev/null
@@ -0,0 +1,215 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Simple publish/subscribe event server.
+
+"""
+import string
+
+from twisted.internet import reactor
+
+# subscribe a.b.c h: map a.b.c -> h
+# subscribe a.b.* h: map a.b.* -> h
+# subscribe a.b.? h: map a.b.? -> h
+#
+# for event a.b.c.d:
+#
+# lookup a.b.c.d, call handlers
+#
+# lookup a.b.c.?, call handlers
+#
+# lookup a.b.c.d.*, call handlers
+# lookup a.b.c.*, call handlers
+# lookup a.b.*, call handlers
+# lookup a.*, call handlers
+# lookup *, call handlers
+
+# a.b.c.d = (a b c d)
+# a.b.c.? = (a b c _)
+# a.b.c.* = (a b c . _)
+
+class EventServer:
+
+    DOT = '.'
+    QUERY = '?'
+    DOT_QUERY = DOT + QUERY
+    STAR = '*'
+    DOT_STAR = DOT + STAR
+
+    def __init__(self, run=0):
+        self.handlers = {}
+        self.run = run
+        self.queue = []
+
+    def start(self):
+        """Enable event handling. Sends any queued events.
+        """
+        self.run = 1
+        for (e,v) in self.queue:
+            self.inject(e, v)
+        self.queue = []
+
+    def stop(self):
+        """Suspend event handling. Events injected while suspended
+        are queued until we are started again.
+        """
+        self.run = 0
+
+    def subscribe(self, event, handler):
+        """Subscribe to an event. For example 'a.b.c.d'.
+        A subcription like 'a.b.c.?' ending in '?' matches any value
+        for the '?'. A subscription like 'a.b.c.*' ending in '*' matches
+        any event type with the same prefix, 'a.b.c' in this case.
+
+        event  event name
+        handler event handler fn(event, val)
+        """
+        hl = self.handlers.get(event)
+        if hl is None:
+            self.handlers[event] = [handler]
+        else:
+            hl.append(handler)
+
+    def unsubscribe_all(self, event=None):
+        """Unsubscribe all handlers for a given event, or all handlers.
+
+        event  event (optional)
+        """
+        if event == None:
+            self.handlers.clear()
+        elif event in self.handlers:
+            del self.handlers[event]
+        
+    def unsubscribe(self, event, handler):
+        """Unsubscribe a given event and handler.
+
+        event  event
+        handler handler
+        """
+        hl = self.handlers.get(event)
+        if hl is None:
+            return
+        if handler in hl:
+            hl.remove(handler)
+
+    def inject(self, event, val, async=1):
+        """Inject an event. Handlers for it are called if running, otherwise
+        it is queued.
+
+        event  event type
+        val    event value
+        """
+        if self.run:
+            if async:
+                reactor.callLater(0, self.call_handlers, event, val)
+            else:
+                self.notify_handlers(event, val)
+        else:
+            self.queue.append( (event, val) )
+
+    def call_handlers(self, event, val):
+        """Internal method to call event handlers.
+        """
+        #print ">event", event, val
+        self.call_event_handlers(event, event, val)
+        self.call_query_handlers(event, val)
+        self.call_star_handlers(event, val)
+
+    def call_event_handlers(self, key, event, val):
+        """Call the handlers for an event.
+        It is safe for handlers to subscribe or unsubscribe.
+
+        key    key for handler list
+        event  event type
+        val    event value
+        """
+        hl = self.handlers.get(key)
+        if hl is None:
+            return
+        # Copy the handler list so that handlers can call
+        # subscribe/unsubscribe safely - python list iteration
+        # is not safe against list modification.
+        for h in hl[:]:
+            try:
+                h(event, val)
+            except:
+                pass
+        
+    def call_query_handlers(self, event, val):
+        """Call regex handlers for events matching 'event' that end in '?'.
+
+        event  event type
+        val    event value
+        """
+        dot_idx = event.rfind(self.DOT)
+        if dot_idx == -1:
+            self.call_event_handlers(self.QUERY, event, val)
+        else:
+            event_query = event[0:dot_idx] + self.DOT_QUERY
+            self.call_event_handlers(event_query, event, val)
+
+    def call_star_handlers(self, event, val):
+        """Call regex handlers for events matching 'event' that end in '*'.
+
+        event  event type
+        val    event value
+        """
+        etype = string.split(event, self.DOT)
+        for i in range(len(etype), 0, -1):
+            event_star = self.DOT.join(etype[0:i]) + self.DOT_STAR
+            self.call_event_handlers(event_star, event, val)
+        self.call_event_handlers(self.STAR, event, val)       
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = EventServer()
+        inst.start()
+    return inst
+
+def main():
+    def sys_star(event, val):
+        print 'sys_star', event, val
+
+    def sys_foo(event, val):
+        print 'sys_foo', event, val
+        s.unsubscribe('sys.foo', sys_foo)
+
+    def sys_foo2(event, val):
+        print 'sys_foo2', event, val
+
+    def sys_bar(event, val):
+        print 'sys_bar', event, val
+
+    def sys_foo_bar(event, val):
+        print 'sys_foo_bar', event, val
+
+    def foo_bar(event, val):
+        print 'foo_bar', event, val
+
+    s = EventServer()
+    s.start()
+    s.subscribe('sys.*', sys_star)
+    s.subscribe('sys.foo', sys_foo)
+    s.subscribe('sys.foo', sys_foo2)
+    s.subscribe('sys.bar', sys_bar)
+    s.subscribe('sys.foo.bar', sys_foo_bar)
+    s.subscribe('foo.bar', foo_bar)
+    s.inject('sys.foo', 'hello')
+    print
+    s.inject('sys.bar', 'hello again')
+    print
+    s.inject('sys.foo.bar', 'hello again')
+    print
+    s.inject('foo.bar', 'hello again')
+    print
+    s.inject('foo', 'hello again')
+    print
+    s.start()
+    s.unsubscribe('sys.*', sys_star)
+    s.unsubscribe_all('sys.*')
+    s.inject('sys.foo', 'hello')
+
+if __name__ == "__main__":
+    main()
+
diff --git a/tools/python/xen/xend/EventTypes.py b/tools/python/xen/xend/EventTypes.py
new file mode 100644 (file)
index 0000000..6350baa
--- /dev/null
@@ -0,0 +1,34 @@
+#   Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+## XEND_DOMAIN_CREATE = "xend.domain.create": dom
+## create: 
+## xend.domain.destroy: dom, reason:died/crashed
+## xend.domain.up ?
+
+## xend.domain.unpause: dom
+## xend.domain.pause: dom
+## xend.domain.shutdown: dom
+## xend.domain.destroy: dom
+
+## xend.domain.migrate.begin: dom, to
+## Begin tells: src host, src domain uri, dst host. Dst id known?
+## err: src host, src domain uri, dst host, dst id if known, status (of domain: ok, dead,...), reason
+## end: src host, src domain uri, dst host, dst uri
+
+## Events for both ends of migrate: for exporter and importer?
+## Include migrate id so can tie together.
+## Have uri /xend/migrate/<id> for migrate info (migrations in progress).
+
+## (xend.domain.migrate.begin (src <host>) (src.domain <id>)
+##                            (dst <host>) (id <migrate id>))
+## xend.domain.migrate.end:
+## (xend.domain.migrate.end (domain <id>) (to <host>)
+
+## xend.node.up:  xend uri
+## xend.node.down: xend uri
+
+## xend.error ?
+
+## format:
+
diff --git a/tools/python/xen/xend/PrettyPrint.py b/tools/python/xen/xend/PrettyPrint.py
new file mode 100644 (file)
index 0000000..9e91b11
--- /dev/null
@@ -0,0 +1,299 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""General pretty-printer, including support for SXP.
+
+"""
+import sys
+import types
+import StringIO
+import sxp
+
+class PrettyItem:
+
+    def __init__(self, width):
+        self.width = width
+
+    def insert(self, block):
+        block.addtoline(self)
+
+    def get_width(self):
+        return self.width
+
+    def output(self, out):
+        print '***PrettyItem>output>', self
+        pass
+
+    def prettyprint(self, out, width):
+        print '***PrettyItem>prettyprint>', self
+        return width
+
+class PrettyString(PrettyItem):
+
+    def __init__(self, x):
+        PrettyItem.__init__(self, len(x))
+        self.value = x
+
+    def output(self, out):
+        out.write(self.value)
+
+    def prettyprint(self, line):
+        line.output(self)
+
+    def show(self, out):
+        print >> out, ("(string (width %d) '%s')" % (self.width, self.value))
+
+class PrettySpace(PrettyItem):
+
+    def output(self, out):
+        out.write(' ' * self.width)
+
+    def prettyprint(self, line):
+        line.output(self)
+
+    def show(self, out):
+        print >> out, ("(space (width %d))" % self.width)
+        
+class PrettyBreak(PrettyItem):
+
+    def __init__(self, width, indent):
+        PrettyItem.__init__(self, width)
+        self.indent = indent
+        self.space = 0
+        self.active = 0
+
+    def output(self, out):
+        out.write(' ' * self.width)
+
+    def prettyprint(self, line):
+        if line.breaks(self.space):
+            self.active = 1
+            line.newline(self.indent)
+        else:
+            line.output(self)
+
+    def show(self, out):
+        print >> out, ("(break (width %d) (indent %d) (space %d) (active %d))"
+                       % (self.width, self.indent, self.space, self.lspace, self.active))
+
+class PrettyNewline(PrettySpace):
+
+    def __init__(self, indent):
+        PrettySpace.__init__(self, indent)
+
+    def insert(self, block):
+        block.newline()
+        block.addtoline(self)
+
+    def output(self, out):
+        out.write(' ' * self.width)
+
+    def prettyprint(self, line):
+        line.newline(0)
+        line.output(self)
+
+    def show(self, out):
+        print >> out, ("(nl (indent %d))" % self.indent)
+
+class PrettyLine(PrettyItem):
+    def __init__(self):
+        PrettyItem.__init__(self, 0)
+        self.content = []
+
+    def write(self, x):
+        self.content.append(x)
+
+    def end(self):
+        width = 0
+        lastwidth = 0
+        lastbreak = None
+        for x in self.content:
+            if isinstance(x, PrettyBreak):
+                if lastbreak:
+                    lastbreak.space = (width - lastwidth)
+                lastbreak = x
+                lastwidth = width
+            width += x.get_width()
+        if lastbreak:
+            lastbreak.space = (width - lastwidth)
+        self.width = width
+    def prettyprint(self, line):
+        for x in self.content:
+            x.prettyprint(line)
+
+    def show(self, out):
+        print >> out, '(LINE (width %d)' % self.width
+        for x in self.content:
+            x.show(out)
+        print >> out, ')'
+
+class PrettyBlock(PrettyItem):
+
+    def __init__(self, all=0, parent=None):
+        self.width = 0
+        self.lines = []
+        self.parent = parent
+        self.indent = 0
+        self.all = all
+        self.broken = 0
+        self.newline()
+
+    def add(self, item):
+        item.insert(self)
+
+    def end(self):
+        self.width = 0
+        for l in self.lines:
+            l.end()
+            if self.width < l.width:
+                self.width = l.width
+
+    def breaks(self, n):
+        return self.all and self.broken
+
+    def newline(self):
+        self.lines.append(PrettyLine())
+
+    def addtoline(self, x):
+        self.lines[-1].write(x)
+
+    def prettyprint(self, line):
+        self.indent = line.used
+        line.block = self
+        if not line.fits(self.width):
+            self.broken = 1
+        for l in self.lines:
+            l.prettyprint(line)
+        line.block = self.parent
+
+    def show(self, out):
+        print >> out, ('(BLOCK (width %d) (indent %d) (all %d) (broken %d)' %
+                       (self.width, self.indent, self.all, self.broken))
+        for l in self.lines:
+            l.show(out)
+        print >> out, ')'
+
+class Line:
+
+    def __init__(self, out, width):
+        self.out = out
+        self.width = width
+        self.used = 0
+        self.space = self.width
+
+    def newline(self, indent):
+        indent += self.block.indent
+        self.out.write('\n')
+        self.out.write(' ' * indent)
+        self.used = indent
+        self.space = self.width - self.used
+
+    def fits(self, n):
+        return self.space - n >= 0
+
+    def breaks(self, n):
+        return self.block.breaks(n) or not self.fits(n)
+
+    def output(self, x):
+        n = x.get_width()
+        self.space -= n
+        self.used += n
+        if self.space < 0:
+            self.space = 0
+        x.output(self.out)
+
+class PrettyPrinter:
+    """A prettyprinter based on what I remember of Derek Oppen's
+    prettyprint algorithm from TOPLAS way back.
+    """
+
+    def __init__(self, width=40):
+        self.width = width
+        self.block = None
+        self.top = None
+
+    def write(self, x):
+        self.block.add(PrettyString(x))
+
+    def add(self, item):
+        self.block.add(item)
+
+    def addbreak(self, width=1, indent=4):
+        self.add(PrettyBreak(width, indent))
+
+    def addspace(self, width=1):
+        self.add(PrettySpace(width))
+
+    def addnl(self, indent=0):
+        self.add(PrettyNewline(indent))
+
+    def begin(self, all=0):
+        block = PrettyBlock(all=all, parent=self.block)
+        self.block = block
+
+    def end(self):
+        self.block.end()
+        if self.block.parent:
+            self.block.parent.add(self.block)
+        else:
+            self.top = self.block
+        self.block = self.block.parent
+
+    def prettyprint(self, out=sys.stdout):
+        line = Line(out, self.width)
+        self.top.prettyprint(line)
+
+class SXPPrettyPrinter(PrettyPrinter):
+    """An SXP prettyprinter.
+    """
+    
+    def pstring(self, x):
+        io = StringIO.StringIO()
+        sxp.show(x, out=io)
+        io.seek(0)
+        val = io.getvalue()
+        io.close()
+        return val
+
+    def pprint(self, l):
+        if isinstance(l, types.ListType):
+            self.begin(all=1)
+            self.write('(')
+            i = 0
+            for x in l:
+                if(i): self.addbreak()
+                self.pprint(x)
+                i += 1
+            self.addbreak(width=0, indent=0)
+            self.write(')')
+            self.end()
+        else:
+            self.write(self.pstring(l))
+
+def prettyprint(sxpr, out=sys.stdout, width=80):
+    """Prettyprint an SXP form.
+
+    sxpr       s-expression
+    out                destination
+    width      maximum output width
+    """
+    if isinstance(sxpr, types.ListType):
+        pp = SXPPrettyPrinter(width=width)
+        pp.pprint(sxpr)
+        pp.prettyprint(out=out)
+    else:
+        sxp.show(sxpr, out=out)
+    print >> out
+
+def main():
+    pin = sxp.Parser()
+    while 1:
+        buf = sys.stdin.read(100)
+        pin.input(buf)
+        if buf == '': break
+    l = pin.get_val()
+    prettyprint(l, width=80)
+
+if __name__ == "__main__":
+    main()
+    
diff --git a/tools/python/xen/xend/Vifctl.py b/tools/python/xen/xend/Vifctl.py
new file mode 100644 (file)
index 0000000..49df8f6
--- /dev/null
@@ -0,0 +1,28 @@
+import os
+import os.path
+import sys
+
+VIFCTL = '/etc/xen/xend/vifctl'
+
+def init():
+    os.system(VIFCTL + ' init ')
+
+def up(vif, mac=None, bridge=None, ipaddr=[]):
+    args = ['vif=%s' % vif]
+    if mac:
+        args.append('mac=%s' % mac)
+    if bridge:
+        args.append('bridge=%s' % bridge)
+    if ipaddr:
+        args.append('ipaddr=%s' % ','.join(ipaddr))
+    os.system(VIFCTL + ' up ' + ' '.join(args))
+
+def down(vif, mac=None, bridge=None, ipaddr=[]):
+    args = ['vif=%s' % vif]
+    if mac:
+        args.append('mac=%s' % mac)
+    if bridge:
+        args.append('bridge=%s' % bridge)
+    if ipaddr:
+        args.append('ipaddr=%s' % ','.join(ipaddr))
+    os.system(VIFCTL + ' down ' + ' '.join(args))
diff --git a/tools/python/xen/xend/XendClient.py b/tools/python/xen/xend/XendClient.py
new file mode 100644 (file)
index 0000000..13dc3db
--- /dev/null
@@ -0,0 +1,311 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Client API for the HTTP interface on xend.
+Callable as a script - see main().
+"""
+import sys
+import httplib
+import types
+from StringIO import StringIO
+import urlparse
+
+from encode import *
+import sxp
+import PrettyPrint
+
+DEBUG = 0
+
+class Foo(httplib.HTTPResponse):
+
+    def begin(self):
+        fin = self.fp
+        while(1):
+            buf = fin.readline()
+            print "***", buf
+            if buf == '':
+                print
+                sys.exit()
+
+
+def sxprio(sxpr):
+    io = StringIO()
+    sxp.show(sxpr, out=io)
+    print >> io
+    io.seek(0)
+    return io
+
+def fileof(val):
+    """Converter for passing configs.
+    Handles lists, files directly.
+    Assumes a string is a file name and passes its contents.
+    """
+    if isinstance(val, types.ListType):
+        return sxprio(val)
+    if isinstance(val, types.StringType):
+        return file(val)
+    if hasattr(val, 'readlines'):
+        return val
+
+# todo: need to sort of what urls/paths are using for objects.
+# e.g. for domains at the moment return '0'.
+# should probably return abs path w.r.t. server, e.g. /xend/domain/0.
+# As an arg, assume abs path is obj uri, otherwise just id.
+
+# Function to convert to full url: Xend.uri(path), e.g.
+# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
+# And should accept urls for ids?
+
+def urljoin(location, root, prefix='', rest=''):
+    prefix = str(prefix)
+    rest = str(rest)
+    base = 'http://' + location + root + prefix
+    url = urlparse.urljoin(base, rest)
+    return url
+
+def nodeurl(location, root, id=''):
+    return urljoin(location, root, 'node/', id)
+
+def domainurl(location, root, id=''):
+    return urljoin(location, root, 'domain/', id)
+
+def consoleurl(location, root, id=''):
+    return urljoin(location, root, 'console/', id)
+
+def deviceurl(location, root, id=''):
+    return urljoin(location, root, 'device/', id)
+
+def vneturl(location, root, id=''):
+    return urljoin(location, root, 'vnet/', id)
+
+def eventurl(location, root, id=''):
+    return urljoin(location, root, 'event/', id)
+
+def xend_request(url, method, data=None):
+    urlinfo = urlparse.urlparse(url)
+    (uproto, ulocation, upath, uparam, uquery, ufrag) = urlinfo
+    if DEBUG: print url, urlinfo
+    if uproto != 'http':
+        raise StandardError('Invalid protocol: ' + uproto)
+    if DEBUG: print '>xend_request', ulocation, upath, method, data
+    (hdr, args) = encode_data(data)
+    if data and method == 'GET':
+        upath += '?' + args
+        args = None
+    if method == "POST" and upath.endswith('/'):
+        upath = upath[:-1]
+    if DEBUG: print "ulocation=", ulocation, "upath=", upath, "args=", args
+    #hdr['User-Agent'] = 'Mozilla'
+    #hdr['Accept'] = 'text/html,text/plain'
+    conn = httplib.HTTPConnection(ulocation)
+    #conn.response_class = Foo
+    if DEBUG: conn.set_debuglevel(1)
+    conn.request(method, upath, args, hdr)
+    resp = conn.getresponse()
+    if DEBUG: print resp.status, resp.reason
+    if DEBUG: print resp.msg.headers
+    if resp.status in [204, 404]:
+        return None
+    if resp.status not in [200, 201, 202, 203]:
+        raise RuntimeError(resp.reason)
+    pin = sxp.Parser()
+    data = resp.read()
+    if DEBUG: print "***data" , data
+    if DEBUG: print "***"
+    pin.input(data);
+    pin.input_eof()
+    conn.close()
+    val = pin.get_val()
+    #if isinstance(val, types.ListType) and sxp.name(val) == 'val':
+    #    val = val[1]
+    if isinstance(val, types.ListType) and sxp.name(val) == 'err':
+        raise RuntimeError(val[1])
+    if DEBUG: print '**val='; sxp.show(val); print
+    return val
+
+def xend_get(url, args=None):
+    return xend_request(url, "GET", args)
+
+def xend_call(url, data):
+    return xend_request(url, "POST", data)
+
+class Xend:
+
+    SRV_DEFAULT = "localhost:8000"
+    ROOT_DEFAULT = "/xend/"
+
+    def __init__(self, srv=None, root=None):
+        self.bind(srv, root)
+
+    def bind(self, srv=None, root=None):
+        if srv is None: srv = self.SRV_DEFAULT
+        if root is None: root = self.ROOT_DEFAULT
+        if not root.endswith('/'): root += '/'
+        self.location = srv
+        self.root = root
+
+    def nodeurl(self, id=''):
+        return nodeurl(self.location, self.root, id)
+
+    def domainurl(self, id=''):
+        return domainurl(self.location, self.root, id)
+
+    def consoleurl(self, id=''):
+        return consoleurl(self.location, self.root, id)
+
+    def deviceurl(self, id=''):
+        return deviceurl(self.location, self.root, id)
+
+    def vneturl(self, id=''):
+        return vneturl(self.location, self.root, id)
+
+    def eventurl(self, id=''):
+        return eventurl(self.location, self.root, id)
+
+    def xend(self):
+        return xend_get(urljoin(self.location, self.root))
+
+    def xend_node(self):
+        return xend_get(self.nodeurl())
+
+    def xend_node_cpu_rrobin_slice_set(self, slice):
+        return xend_call(self.nodeurl(),
+                         {'op'      : 'cpu_rrobin_slice_set',
+                          'slice'   : slice })
+    
+    def xend_node_cpu_bvt_slice_set(self, slice):
+        return xend_call(self.nodeurl(),
+                         {'op'      : 'cpu_bvt_slice_set',
+                          'slice'   : slice })
+
+    def xend_domains(self):
+        return xend_get(self.domainurl())
+
+    def xend_domain_create(self, conf):
+        return xend_call(self.domainurl(),
+                         {'op'      : 'create',
+                          'config'  : fileof(conf) })
+
+    def xend_domain(self, id):
+        return xend_get(self.domainurl(id))
+
+    def xend_domain_unpause(self, id):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'unpause'})
+
+    def xend_domain_pause(self, id):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'pause'})
+
+    def xend_domain_shutdown(self, id):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'shutdown'})
+
+    def xend_domain_destroy(self, id):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'destroy'})
+
+    def xend_domain_save(self, id, filename):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'save',
+                          'file'    : filename})
+
+    def xend_domain_restore(self, id, filename):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'restore',
+                          'file'    : filename })
+
+    def xend_domain_migrate(self, id, dst):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'migrate',
+                          'destination': dst})
+
+    def xend_domain_pincpu(self, id, cpu):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'pincpu',
+                          'cpu'     : cpu})
+
+    def xend_domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'cpu_bvt_set',
+                          'mcuadv'  : mvuadv,
+                          'warp'    : warp,
+                          'warpl'   : warpl,
+                          'warpu'   : warpu })
+
+    def xend_domain_cpu_atropos_set(self, id, period, slice, latency, xtratime):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'cpu_atropos_set',
+                          'period'  : period,
+                          'slice'   : slice,
+                          'latency' : latency,
+                          'xtratime': xtratime })
+
+    def xend_domain_vifs(self, id):
+        return xend_get(self.domainurl(id),
+                        { 'op'      : 'vifs' })
+    
+    def xend_domain_vif_ip_add(self, id, vif, ipaddr):
+        return xend_call(self.domainurl(id),
+                         {'op'      : 'vif_ip_add',
+                          'vif'     : vif,
+                          'ip'      : ipaddr })
+        
+    def xend_domain_vbds(self, id):
+        return xend_get(self.domainurl(id),
+                        {'op'       : 'vbds'})
+
+    def xend_domain_vbd(self, id, vbd):
+        return xend_get(self.domainurl(id),
+                        {'op'       : 'vbd',
+                         'vbd'      : vbd})
+
+    def xend_consoles(self):
+        return xend_get(self.consoleurl())
+
+    def xend_console(self, id):
+        return xend_get(self.consoleurl(id))
+
+    def xend_vnets(self):
+        return xend_get(self.vneturl())
+
+    def xend_vnet_create(self, conf):
+        return xend_call(self.vneturl(),
+                         {'op': 'create', 'config': fileof(conf) })
+
+    def xend_vnet(self, id):
+        return xend_get(self.vneturl(id))
+
+    def xend_vnet_delete(self, id):
+        return xend_call(self.vneturl(id),
+                         {'op': 'delete'})
+
+    def xend_event_inject(self, sxpr):
+        val = xend_call(self.eventurl(),
+                        {'op': 'inject', 'event': fileof(sxpr) })
+    
+
+def main(argv):
+    """Call an API function:
+    
+    python XendClient.py fn args...
+
+    The leading 'xend_' on the function can be omitted.
+    Example:
+
+    > python XendClient.py domains
+    (domain 0 8)
+    > python XendClient.py domain 0
+    (domain (id 0) (name Domain-0) (memory 128))
+    """
+    server = Xend()
+    fn = argv[1]
+    if not fn.startswith('xend'):
+        fn = 'xend_' + fn
+    args = argv[2:]
+    val = getattr(server, fn)(*args)
+    PrettyPrint.prettyprint(val)
+    print
+
+if __name__ == "__main__":
+    main(sys.argv)
+else:    
+    server = Xend()
diff --git a/tools/python/xen/xend/XendConsole.py b/tools/python/xen/xend/XendConsole.py
new file mode 100644 (file)
index 0000000..4420c38
--- /dev/null
@@ -0,0 +1,179 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+import socket
+import xen.ext.xc
+xc = xen.ext.xc.new()
+
+import sxp
+import XendRoot
+xroot = XendRoot.instance()
+import XendDB
+
+import EventServer
+eserver = EventServer.instance()
+
+from xen.xend.server import SrvDaemon
+daemon = SrvDaemon.instance()
+
+class XendConsoleInfo:
+    """Console information record.
+    """
+
+    def __init__(self, console, dom1, port1, dom2, port2, conn=None):
+        self.console = console
+        self.dom1  = int(dom1)
+        self.port1 = int(port1)
+        self.dom2  = int(dom2)
+        self.port2 = int(port2)
+        self.conn  = conn
+        #self.id = "%d.%d-%d.%d" % (self.dom1, self.port1, self.dom2, self.port2)
+        self.id = str(port1)
+
+    def __str__(self):
+        s = "console"
+        s += " id=%s" % self.id
+        s += " src=%d.%d" % (self.dom1, self.port1)
+        s += " dst=%d.%d" % (self.dom2, self.port2)
+        s += " port=%s" % self.console
+        if self.conn:
+            s += " conn=%s:%s" % (self.conn[0], self.conn[1])
+        return s
+
+    def sxpr(self):
+        sxpr = ['console',
+                ['id', self.id],
+                ['src', self.dom1, self.port1],
+                ['dst', self.dom2, self.port2],
+                ['port', self.console],
+                ]
+        if self.conn:
+            sxpr.append(['connected', self.conn[0], self.conn[1]])
+        return sxpr
+
+    def connection(self):
+        return self.conn
+
+    def update(self, consinfo):
+        conn = sxp.child(consinfo, 'connected')
+        if conn:
+            self.conn = conn[1:]
+        else:
+            self.conn = None
+
+    def uri(self):
+        """Get the uri to use to connect to the console.
+        This will be a telnet: uri.
+
+        return uri
+        """
+        host = socket.gethostname()
+        return "telnet://%s:%s" % (host, self.console)
+
+class XendConsole:
+
+    dbpath = "console"
+
+    def  __init__(self):
+        self.db = XendDB.XendDB(self.dbpath)
+        self.console = {}
+        self.console_db = self.db.fetchall("")
+        if xroot.get_rebooted():
+            print 'XendConsole> rebooted: removing all console info'
+            self.rm_all()
+        eserver.subscribe('xend.domain.died', self.onDomainDied)
+        eserver.subscribe('xend.domain.destroy', self.onDomainDied)
+
+    def rm_all(self):
+        """Remove all console info. Used after reboot.
+        """
+        for (k, v) in self.console_db.items():
+            self._delete_console(k)
+
+    def refresh(self):
+        consoles = daemon.consoles()
+        cons = {}
+        for consinfo in consoles:
+            id = str(sxp.child_value(consinfo, 'id'))
+            cons[id] = consinfo
+            if id not in self.console:
+                self._new_console(consinfo)
+        for c in self.console.values():
+            consinfo = cons.get(c.id)
+            if consinfo:
+                c.update(consinfo)
+            else:
+                self._delete_console(c.id)
+
+    def onDomainDied(self, event, val):
+        dom = int(val)
+        #print 'XendConsole>onDomainDied', 'event', event, "dom=", dom
+        for c in self.consoles():
+            #print 'onDomainDied', "dom=", dom, "dom1=", c.dom1, "dom2=", c.dom2
+            if (c.dom1 == dom) or (c.dom2 == dom):
+                'XendConsole>onDomainDied', 'delete console dom=', dom
+                ctrl = daemon.get_domain_console(dom)
+                if ctrl:
+                    ctrl.close()
+                self._delete_console(c.id)
+
+    def sync(self):
+        self.db.saveall("", self.console_db)
+
+    def sync_console(self, id):
+        self.db.save(id, self.console_db[id])
+
+    def _new_console(self, consinfo):
+        # todo: xen needs a call to get current domain id.
+        dom1 = 0
+        port1 = sxp.child_value(consinfo, 'local_port')
+        dom2 = sxp.child_value(consinfo, 'domain')
+        port2 = sxp.child_value(consinfo, 'remote_port')
+        console = sxp.child_value(consinfo, 'console_port')
+        info = XendConsoleInfo(console, dom1, int(port1), int(dom2), int(port2))
+        info.update(consinfo)
+        self._add_console(info.id, info)
+        return info
+
+    def _add_console(self, id, info):
+        self.console[id] = info
+        self.console_db[id] = info.sxpr()
+        self.sync_console(id)
+
+    def _delete_console(self, id):
+        if id in self.console:
+            del self.console[id]
+        if id in self.console_db:
+            del self.console_db[id]
+            self.db.delete(id)
+
+    def console_ls(self):
+        self.refresh()
+        return self.console.keys()
+
+    def consoles(self):
+        self.refresh()
+        return self.console.values()
+    
+    def console_create(self, dom):
+        consinfo = daemon.console_create(dom)
+        info = self._new_console(consinfo)
+        return info
+    
+    def console_get(self, id):
+        self.refresh()
+        return self.console.get(id)
+
+    def console_delete(self, id):
+        self._delete_console(id)
+
+    def console_disconnect(self, id):
+        id = int(id)
+        daemon.console_disconnect(id)
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendConsole()
+    return inst
diff --git a/tools/python/xen/xend/XendDB.py b/tools/python/xen/xend/XendDB.py
new file mode 100644 (file)
index 0000000..6a27e65
--- /dev/null
@@ -0,0 +1,91 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+import os
+import os.path
+import errno
+import dircache
+import time
+
+import sxp
+import XendRoot
+xroot = XendRoot.instance()
+
+class XendDB:
+    """Persistence for Xend. Stores data in files and directories.
+    """
+
+    def __init__(self, path=None):
+        self.dbpath = xroot.get_dbroot()
+        if path:
+            self.dbpath = os.path.join(self.dbpath, path)
+        pass
+
+    def filepath(self, path):
+        return os.path.join(self.dbpath, path)
+        
+    def fetch(self, path):
+        fpath = self.filepath(path)
+        return self.fetchfile(fpath)
+
+    def fetchfile(self, fpath):
+        pin = sxp.Parser()
+        fin = file(fpath, "rb")
+        try:
+            while 1:
+                try:
+                    buf = fin.read(1024)
+                except IOError, ex:
+                    if ex.errno == errno.EINTR:
+                        continue
+                    else:
+                        raise
+                pin.input(buf)
+                if buf == '':
+                    pin.input_eof()
+                    break
+        finally:
+            fin.close()
+        return pin.get_val()
+
+    def save(self, path, sxpr):
+        fpath = self.filepath(path)
+        return self.savefile(fpath, sxpr)
+    
+    def savefile(self, fpath, sxpr):
+        fdir = os.path.dirname(fpath)
+        if not os.path.isdir(fdir):
+            os.makedirs(fdir)
+        fout = file(fpath, "wb+")
+        try:
+            t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
+            fout.write("# %s %s\n" % (fpath, t))
+            sxp.show(sxpr, out=fout)
+        finally:
+            fout.close()
+
+    def fetchall(self, path):
+        dpath = self.filepath(path)
+        d = {}
+        for k in dircache.listdir(dpath):
+            try:
+                v = self.fetchfile(os.path.join(dpath, k))
+                d[k] = v
+            except:
+                pass
+        return d
+
+    def saveall(self, path, d):
+        for (k, v) in d.items():
+            self.save(os.path.join(path, k), v)
+
+    def delete(self, path):
+        dpath = self.filepath(path)
+        os.unlink(dpath)
+
+    def ls(self, path):
+        dpath = self.filepath(path)
+        return dircache.listdir(dpath)
+            
+        
+
+        
diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py
new file mode 100644 (file)
index 0000000..3aaf080
--- /dev/null
@@ -0,0 +1,369 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Handler for domain operations.
+ Nothing here is persistent (across reboots).
+ Needs to be persistent for one uptime.
+"""
+import sys
+
+from twisted.internet import defer
+
+import xen.ext.xc; xc = xen.ext.xc.new()
+
+import sxp
+import XendRoot
+xroot = XendRoot.instance()
+import XendDB
+import XendDomainInfo
+import XendConsole
+import EventServer
+
+from xen.xend.server import SrvDaemon
+xend = SrvDaemon.instance()
+
+eserver = EventServer.instance()
+
+__all__ = [ "XendDomain" ]
+        
+class XendDomain:
+    """Index of all domains. Singleton.
+    """
+    
+    dbpath = "domain"
+    domain = {}
+    
+    def __init__(self):
+        self.xconsole = XendConsole.instance()
+        # Table of domain info indexed by domain id.
+        self.db = XendDB.XendDB(self.dbpath)
+        #self.domain = {}
+        self.domain_db = self.db.fetchall("")
+        if xroot.get_rebooted():
+            print 'XendDomain> rebooted: removing all domain info'
+            self.rm_all()
+        eserver.subscribe('xend.virq', self.onVirq)
+        self.initial_refresh()
+
+    def onVirq(self, event, val):
+        print 'XendDomain> virq', val
+        self.reap()
+
+    def rm_all(self):
+        """Remove all domain info. Used after reboot.
+        """
+        for (k, v) in self.domain_db.items():
+            self._delete_domain(k, notify=0)
+            
+    def initial_refresh(self):
+        """Refresh initial domain info from domain_db.
+        """
+        print "initial_refresh>"
+        for d in self.domain_db.values(): print 'db dom=', d
+        domlist = xc.domain_getinfo()
+        for d in domlist: print 'xc dom=', d
+        doms = {}
+        for d in domlist:
+            domid = str(d['dom'])
+            doms[domid] = d
+        dlist = []
+        for config in self.domain_db.values():
+            domid = str(sxp.child_value(config, 'id'))
+            print "dom=", domid, "config=", config
+            if domid in doms:
+                print "dom=", domid, "new"
+                deferred = self._new_domain(config, doms[domid])
+                dlist.append(deferred)
+            else:
+                print "dom=", domid, "del"
+                self._delete_domain(domid)
+        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
+        def cbok(val):
+            #print "doms:"
+            #for d in self.domain.values(): print 'dom', d
+            self.refresh()
+            print "XendDomain>initial_refresh> doms:"
+            for d in self.domain.values(): print 'dom', d
+        deferred.addCallback(cbok)
+
+    def sync(self):
+        """Sync domain db to disk.
+        """
+        self.db.saveall("", self.domain_db)
+
+    def sync_domain(self, dom):
+        """Sync info for a domain to disk.
+
+        dom    domain id (string)
+        """
+        self.db.save(dom, self.domain_db[dom])
+
+    def close(self):
+        pass
+
+    def _new_domain(self, savedinfo, info):
+        """Create a domain entry from saved info.
+        """
+##         console = None
+##         kernel = None
+##         id = sxp.child_value(info, 'id')
+##         dom = int(id)
+##         name = sxp.child_value(info, 'name')
+##         memory = int(sxp.child_value(info, 'memory'))
+##         consoleinfo = sxp.child(info, 'console')
+##         if consoleinfo:
+##             consoleid = sxp.child_value(consoleinfo, 'id')
+##             console = self.xconsole.console_get(consoleid)
+##         if dom and console is None:
+##             # Try to connect a console.
+##             console = self.xconsole.console_create(dom)
+##         config = sxp.child(info, 'config')
+##         if config:
+##             image = sxp.child(info, 'image')
+##             if image:
+##                 image = sxp.child0(image)
+##                 kernel = sxp.child_value(image, 'kernel')
+##         dominfo = XendDomainInfo.XendDomainInfo(
+##             config, dom, name, memory, kernel, console)
+        config = sxp.child_value(savedinfo, 'config')
+        deferred = XendDomainInfo.vm_recreate(config, info)
+        def fn(dominfo):
+            self.domain[dominfo.id] = dominfo
+        deferred.addCallback(fn)
+        return deferred
+
+    def _add_domain(self, id, info, notify=1):
+        self.domain[id] = info
+        self.domain_db[id] = info.sxpr()
+        self.sync_domain(id)
+        if notify: eserver.inject('xend.domain.created', id)
+
+    def _delete_domain(self, id, notify=1):
+        if id in self.domain:
+            if notify: eserver.inject('xend.domain.died', id)
+            del self.domain[id]
+        if id in self.domain_db:
+            del self.domain_db[id]
+            self.db.delete(id)
+
+    def reap(self):
+        """Go through the domains looking for ones that have crashed or stopped.
+        Tidy them up.
+        """
+        print 'XendDomain>reap>'
+        domlist = xc.domain_getinfo()
+        casualties = []
+        for d in domlist:
+            #print 'dom', d
+            dead = 0
+            dead = dead or (d['crashed'] or d['shutdown'])
+            dead = dead or (d['dying'] and
+                            not(d['running'] or d['paused'] or d['blocked']))
+            if dead:
+                casualties.append(d)
+        for d in casualties:
+            id = str(d['dom'])
+            print 'XendDomain>reap> died id=', id, d
+            dominfo = self.domain.get(id)
+            if not dominfo: continue
+            dominfo.died()
+            self.domain_destroy(id, refresh=0)
+        print 'XendDomain>reap<'
+
+    def refresh(self):
+        """Refresh domain list from Xen.
+        """
+        domlist = xc.domain_getinfo()
+        # Index the domlist by id.
+        # Add entries for any domains we don't know about.
+        doms = {}
+        for d in domlist:
+            id = str(d['dom'])
+            doms[id] = d
+            if id not in self.domain:
+                config = None
+                #image = None
+                #newinfo = XendDomainInfo.XendDomainInfo(
+                #    config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d)
+                deferred = XendDomainInfo.vm_recreate(config, d)
+                def fn(dominfo):
+                    self._add_domain(dominfo.id, dominfo)
+                deferred.addCallback(fn)
+        # Remove entries for domains that no longer exist.
+        for d in self.domain.values():
+            dominfo = doms.get(d.id)
+            if dominfo:
+                d.update(dominfo)
+            else:
+                self._delete_domain(d.id)
+        self.reap()
+
+    def refresh_domain(self, id):
+        dom = int(id)
+        dominfo = xc.domain_getinfo(dom, 1)
+        if dominfo == [] or dominfo[0]['dom'] != dom:
+            try:
+                self._delete_domain(id)
+            except:
+                print 'refresh_domain: error'
+                raise
+                pass
+        else:
+            d = self.domain.get(id)
+            if d:
+                d.update(dominfo[0])
+
+    def domain_ls(self):
+        # List domains.
+        # Update info from kernel first.
+        self.refresh()
+        return self.domain.keys()
+
+    def domains(self):
+        self.refresh()
+        return self.domain.values()
+    
+    def domain_create(self, config):
+        # Create domain, log it.
+        deferred = XendDomainInfo.vm_create(config)
+        def fn(dominfo):
+            self._add_domain(dominfo.id, dominfo)
+            return dominfo
+        deferred.addCallback(fn)
+        return deferred
+    
+    def domain_get(self, id):
+        id = str(id)
+        self.refresh_domain(id)
+        return self.domain.get(id)
+    
+    def domain_unpause(self, id):
+        """(Re)start domain running.
+        """
+        dom = int(id)
+        eserver.inject('xend.domain.unpause', id)
+        return xc.domain_unpause(dom=dom)
+    
+    def domain_pause(self, id):
+        """Pause domain execution.
+        """
+        dom = int(id)
+        eserver.inject('xend.domain.pause', id)
+        return xc.domain_pause(dom=dom)
+    
+    def domain_shutdown(self, id, reason='poweroff'):
+        """Shutdown domain (nicely).
+        """
+        dom = int(id)
+        if dom <= 0:
+            return 0
+        eserver.inject('xend.domain.shutdown', [id, reason])
+        val = xend.domain_shutdown(dom, reason)
+        self.refresh()
+        return val
+    
+    def domain_destroy(self, id, refresh=1):
+        """Terminate domain immediately.
+        """
+        dom = int(id)
+        if dom <= 0:
+            return 0
+        eserver.inject('xend.domain.destroy', id)
+        val = xc.domain_destroy(dom=dom)
+        if refresh: self.refresh()
+        return val       
+
+    def domain_migrate(self, id, dst):
+        """Start domain migration.
+        """
+        # Need a cancel too?
+        pass
+
+    def domain_save(self, id, dst, progress=0):
+        """Save domain state to file, destroy domain.
+        """
+        dom = int(id)
+        dominfo = self.domain_get(id)
+        if not dominfo:
+            return -1
+        vmconfig = sxp.to_string(dominfo.sxpr())
+        self.domain_pause(id)
+        eserver.inject('xend.domain.save', id)
+        rc = xc.linux_save(dom=dom, state_file=dst, vmconfig=vmconfig, progress=progress)
+        if rc == 0:
+            self.domain_destroy(id)
+        return rc
+    
+    def domain_restore(self, src, progress=0):
+        """Restore domain from file.
+        """
+        dominfo = XendDomainInfo.vm_restore(src, progress=progress)
+        self._add_domain(dominfo.id, dominfo)
+        return dominfo
+    
+    #============================================================================
+    # Backward compatibility stuff from here on.
+
+    def domain_pincpu(self, dom, cpu):
+        dom = int(dom)
+        return xc.domain_pincpu(dom, cpu)
+
+    def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu):
+        dom = int(dom)
+        return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv,
+                                      warp=warp, warpl=warpl, warpu=warpu)
+
+    def domain_cpu_bvt_get(self, dom):
+        dom = int(dom)
+        return xc.bvtsched_domain_get(dom)
+    
+    def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime):
+        dom = int(dom)
+        return xc.atropos_domain_set(dom, period, slice, latency, xtratime)
+
+    def domain_cpu_atropos_get(self, dom):
+        dom = int(dom)
+        return xc.atropos_domain_get(dom)
+
+    def domain_vif_ls(self, dom):
+        dominfo = self.domain_get(dom)
+        if not dominfo: return None
+        devs = dominfo.get_devices('vif')
+        return range(0, len(devs))
+
+    def domain_vif_get(self, dom, vif):
+        dominfo = self.domain_get(dom)
+        if not dominfo: return None
+        return dominfo.get_device_by_index(vif)
+
+##     def domain_vif_ip_add(self, dom, vif, ip):
+##         dom = int(dom)
+##         return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip)
+
+    def domain_vbd_ls(self, dom):
+        dominfo = self.domain_get(dom)
+        if not dominfo: return []
+        devs = dominfo.get_devices('vbd')
+        return [ sxp.child_value(v, 'dev') for v in devs ]
+
+    def domain_vbd_get(self, dom, vbd):
+        dominfo = self.domain_get(dom)
+        if not dominfo: return None
+        devs = dominfo.get_devices('vbd')
+        for v in devs:
+            if sxp.child_value(v, 'dev') == vbd:
+                return v
+        return None
+
+    def domain_shadow_control(self, dom, op):
+        dom = int(dom)
+        return xc.shadow_control(dom, op)
+
+    #============================================================================
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendDomain()
+    return inst
diff --git a/tools/python/xen/xend/XendDomainConfig.py b/tools/python/xen/xend/XendDomainConfig.py
new file mode 100644 (file)
index 0000000..35db31f
--- /dev/null
@@ -0,0 +1,44 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Handler for persistent domain configs.
+
+"""
+
+import sxp
+import XendDB
+import XendDomain
+
+__all__ = [ "XendDomainConfig" ]
+
+class XendDomainConfig:
+
+    dbpath = 'config'
+
+    def __init__(self):
+        self.db = XendDB.XendDB(self.dbpath)
+
+    def domain_config_ls(self, path):
+        return self.db.ls(path)
+
+    def domain_config_create(self, path, sxpr):
+        self.db.save(path, sxpr)
+        pass
+
+    def domain_config_delete(self, path):
+        self.db.delete(path)
+
+    def domain_config_instance(self, path):
+        """Create a domain from a config.
+        """
+        config = self.db.fetch(path)
+        xd = XendDomain.instance()
+        newdom = xd.domain_create(config)
+        return newdom
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendDomainConfig()
+    return inst
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
new file mode 100644 (file)
index 0000000..a7e5aa3
--- /dev/null
@@ -0,0 +1,908 @@
+#!/usr/bin/python
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Representation of a single domain.
+Includes support for domain construction, using
+open-ended configurations.
+
+Author: Mike Wray <mike.wray@hpl.hp.com>
+
+"""
+
+import string
+import re
+import sys
+import os
+
+from twisted.internet import defer
+
+import xen.ext.xc; xc = xen.ext.xc.new()
+import xen.util.ip
+
+import sxp
+
+import XendConsole
+xendConsole = XendConsole.instance()
+
+import server.SrvDaemon
+xend = server.SrvDaemon.instance()
+
+SIF_BLK_BE_DOMAIN = (1<<4)
+SIF_NET_BE_DOMAIN = (1<<5)
+
+def readlines(fd):
+    """Version of readlines safe against EINTR.
+    """
+    import errno
+    
+    lines = []
+    while 1:
+        try:
+            line = fd.readline()
+        except IOError, ex:
+            if ex.errno == errno.EINTR:
+                continue
+            else:
+                raise
+        if line == '': break
+        lines.append(line)
+    return lines
+
+class VmError(ValueError):
+    """Vm construction error."""
+
+    def __init__(self, value):
+        self.value = value
+
+    def __str__(self):
+        return self.value
+
+
+def blkdev_name_to_number(name):
+    """Take the given textual block-device name (e.g., '/dev/sda1',
+    'hda') and return the device number used by the OS. """
+
+    if not re.match( '/dev/', name ):
+        name = '/dev/' + name
+        
+    return os.stat(name).st_rdev
+
+def lookup_raw_partn(partition):
+    """Take the given block-device name (e.g., '/dev/sda1', 'hda')
+    and return a dictionary { device, start_sector,
+    nr_sectors, type }
+        device:       Device number of the given partition
+        start_sector: Index of first sector of the partition
+        nr_sectors:   Number of sectors comprising this partition
+        type:         'Disk' or identifying name for partition type
+    """
+
+    if not re.match( '/dev/', partition ):
+        partition = '/dev/' + partition
+
+    drive = re.split( '[0-9]', partition )[0]
+
+    if drive == partition:
+        fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
+        line = readline(fd)
+        if line:
+            return [ { 'device' : blkdev_name_to_number(drive),
+                       'start_sector' : long(0),
+                       'nr_sectors' : long(line) * 2,
+                       'type' : 'Disk' } ]
+        return None
+
+    # determine position on disk
+    fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' )
+
+    #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012']
+    lines = readlines(fd)
+    for line in lines:
+        m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
+                       'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
+        if m:
+            return [ { 'device' : blkdev_name_to_number(drive),
+                       'start_sector' : long(m.group(1)),
+                       'nr_sectors' : long(m.group(2)),
+                       'type' : m.group(3) } ]
+    
+    return None
+
+def lookup_disk_uname(uname):
+    """Lookup a list of segments for a physical device.
+    uname [string]:  name of the device in the format \'phy:dev\' for a physical device
+    returns [list of dicts]: list of extents that make up the named device
+    """
+    ( type, d_name ) = string.split( uname, ':' )
+
+    if type == "phy":
+        segments = lookup_raw_partn( d_name )
+    else:
+        segments = None
+    return segments
+
+def make_disk(dom, uname, dev, mode, recreate=0):
+    """Create a virtual disk device for a domain.
+
+    @returns Deferred
+    """
+    segments = lookup_disk_uname(uname)
+    if not segments:
+        raise VmError("vbd: Segments not found: uname=%s" % uname)
+    if len(segments) > 1:
+        raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname)
+    segment = segments[0]
+    vdev = blkdev_name_to_number(dev)
+    ctrl = xend.blkif_create(dom, recreate=recreate)
+    
+    def fn(ctrl):
+        return xend.blkif_dev_create(dom, vdev, mode, segment, recreate=recreate)
+    ctrl.addCallback(fn)
+    return ctrl
+        
+def make_vif(dom, vif, vmac, recreate=0):
+    """Create a virtual network device for a domain.
+
+    
+    @returns Deferred
+    """
+    xend.netif_create(dom, recreate=recreate)
+    d = xend.netif_dev_create(dom, vif, vmac, recreate=recreate)
+    return d
+
+def vif_up(iplist):
+    """send an unsolicited ARP reply for all non link-local IP addresses.
+
+    iplist IP addresses
+    """
+
+    IP_NONLOCAL_BIND = '/proc/sys/net/ipv4/ip_nonlocal_bind'
+    
+    def get_ip_nonlocal_bind():
+        return int(open(IP_NONLOCAL_BIND, 'r').read()[0])
+
+    def set_ip_nonlocal_bind(v):
+        print >> open(IP_NONLOCAL_BIND, 'w'), str(v)
+
+    def link_local(ip):
+        return xen.util.ip.check_subnet(ip, '169.254.0.0', '255.255.0.0')
+
+    def arping(ip, gw):
+        cmd = '/usr/sbin/arping -A -b -I eth0 -c 1 -s %s %s' % (ip, gw)
+        print cmd
+        os.system(cmd)
+        
+    gateway = xen.util.ip.get_current_ipgw() or '255.255.255.255'
+    nlb = get_ip_nonlocal_bind()
+    if not nlb: set_ip_nonlocal_bind(1)
+    try:
+        for ip in iplist:
+            if not link_local(ip):
+                arping(ip, gateway)
+    finally:
+        if not nlb: set_ip_nonlocal_bind(0)
+
+config_handlers = {}
+
+def add_config_handler(name, h):
+    """Add a handler for a config field.
+
+    name     field name
+    h        handler: fn(vm, config, field, index)
+    """
+    config_handlers[name] = h
+
+def get_config_handler(name):
+    """Get a handler for a config field.
+
+    returns handler or None
+    """
+    return config_handlers.get(name)
+
+"""Table of handlers for virtual machine images.
+Indexed by image type.
+"""
+image_handlers = {}
+
+def add_image_handler(name, h):
+    """Add a handler for an image type
+    name     image type
+    h        handler: fn(config, name, memory, image)
+    """
+    image_handlers[name] = h
+
+def get_image_handler(name):
+    """Get the handler for an image type.
+    name     image type
+
+    returns handler or None
+    """
+    return image_handlers.get(name)
+
+"""Table of handlers for devices.
+Indexed by device type.
+"""
+device_handlers = {}
+
+def add_device_handler(name, h):
+    """Add a handler for a device type.
+
+    name      device type
+    h         handler: fn(vm, dev)
+    """
+    device_handlers[name] = h
+
+def get_device_handler(name):
+    """Get the handler for a device type.
+
+    name      device type
+
+    returns handler or None
+    """
+    return device_handlers.get(name)
+
+def vm_create(config):
+    """Create a VM from a configuration.
+    If a vm has been partially created and there is an error it
+    is destroyed.
+
+    config    configuration
+
+    returns Deferred
+    raises VmError for invalid configuration
+    """
+    print 'vm_create>'
+    vm = XendDomainInfo()
+    return vm.construct(config)
+
+def vm_recreate(config, info):
+    """Create the VM object for an existing domain.
+    """
+    vm = XendDomainInfo()
+    vm.recreate = 1
+    vm.setdom(info['dom'])
+    vm.name = info['name']
+    vm.memory = info['mem_kb']/1024
+    if config:
+        d = vm.construct(config)
+    else:
+        d = defer.Deferred()
+        d.callback(vm)
+    return d
+
+def vm_restore(src, progress=0):
+    """Restore a VM from a disk image.
+
+    src      saved state to restore
+    progress progress reporting flag
+    returns  deferred
+    raises   VmError for invalid configuration
+    """
+    vm = XendDomainInfo()
+    ostype = "linux" #todo Set from somewhere (store in the src?).
+    restorefn = getattr(xc, "%s_restore" % ostype)
+    d = restorefn(state_file=src, progress=progress)
+    dom = int(d['dom'])
+    if dom < 0:
+        raise VMError('restore failed')
+    vmconfig = sxp.from_string(d['vmconfig'])
+    vm.config = sxp.child_value(vmconfig, 'config')
+    deferred = vm.dom_configure(dom)
+    def vifs_cb(val, vm):
+        vif_up(vm.ipaddrs)
+    deferred.addCallback(vifs_cb, vm)
+    return deferred
+    
+def dom_get(dom):
+    domlist = xc.domain_getinfo(dom=dom)
+    if domlist and dom == domlist[0]['dom']:
+        return domlist[0]
+    return None
+    
+
+def append_deferred(dlist, v):
+    if isinstance(v, defer.Deferred):
+        dlist.append(v)
+
+def _vm_configure1(val, vm):
+    d = vm.create_devices()
+    print '_vm_configure1> made devices...'
+    def cbok(x):
+        print '_vm_configure1> cbok', x
+        return x
+    d.addCallback(cbok)
+    d.addCallback(_vm_configure2, vm)
+    print '_vm_configure1<'
+    return d
+
+def _vm_configure2(val, vm):
+    print '>callback _vm_configure2...'
+    d = vm.configure_fields()
+    def cbok(results):
+        print '_vm_configure2> cbok', results
+        return vm
+    def cberr(err):
+        print '_vm_configure2> cberr', err
+        vm.destroy()
+        return err
+    d.addCallback(cbok)
+    d.addErrback(cberr)
+    print '<_vm_configure2'
+    return d
+
+class XendDomainInfo:
+    """Virtual machine object."""
+
+    def __init__(self):
+        self.recreate = 0
+        self.config = None
+        self.id = None
+        self.dom = None
+        self.name = None
+        self.memory = None
+        self.image = None
+        self.ramdisk = None
+        self.cmdline = None
+        self.console = None
+        self.devices = {}
+        self.configs = []
+        self.info = None
+        self.ipaddrs = []
+        self.blkif_backend = 0
+        self.netif_backend = 0
+        #todo: state: running, suspended
+        self.state = 'running'
+        #todo: set to migrate info if migrating
+        self.migrate = None
+
+    def setdom(self, dom):
+        self.dom = int(dom)
+        self.id = str(dom)
+        
+    def update(self, info):
+        """Update with  info from xc.domain_getinfo().
+        """
+        self.info = info
+        self.memory = self.info['mem_kb'] / 1024
+
+    def __str__(self):
+        s = "domain"
+        s += " id=" + self.id
+        s += " name=" + self.name
+        s += " memory=" + str(self.memory)
+        if self.console:
+            s += " console=" + self.console.id
+        if self.image:
+            s += " image=" + self.image
+        s += ""
+        return s
+
+    __repr__ = __str__
+
+    def sxpr(self):
+        sxpr = ['domain',
+                ['id', self.id],
+                ['name', self.name],
+                ['memory', self.memory] ]
+        if self.info:
+            run   = (self.info['running'] and 'r') or '-'
+            block = (self.info['blocked'] and 'b') or '-'
+            stop  = (self.info['paused']  and 'p') or '-'
+            susp  = (self.info['shutdown'] and 's') or '-'
+            crash = (self.info['crashed'] and 'c') or '-'
+            state = run + block + stop + susp + crash
+            sxpr.append(['state', state])
+            if self.info['shutdown']:
+                reasons = ["poweroff", "reboot", "suspend"]
+                reason = reasons[self.info['shutdown_reason']]
+                sxpr.append(['shutdown_reason', reason])
+            sxpr.append(['cpu', self.info['cpu']])
+            sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
+        if self.console:
+            sxpr.append(self.console.sxpr())
+        if self.config:
+            sxpr.append(['config', self.config])
+        return sxpr
+
+    def construct(self, config):
+        # todo - add support for scheduling params?
+        self.config = config
+        try:
+            self.name = sxp.child_value(config, 'name')
+            self.memory = int(sxp.child_value(config, 'memory', '128'))
+            self.configure_backends()
+            image = sxp.child_value(config, 'image')
+            image_name = sxp.name(image)
+            image_handler = get_image_handler(image_name)
+            if image_handler is None:
+                raise VmError('unknown image type: ' + image_name)
+            image_handler(self, image)
+            deferred = self.configure()
+        except StandardError, ex:
+            # Catch errors, cleanup and re-raise.
+            self.destroy()
+            raise
+        def cbok(x):
+            print 'vm_create> cbok', x
+            return x
+        deferred.addCallback(cbok)
+        print 'vm_create<'
+        return deferred
+
+    def config_devices(self, name):
+        """Get a list of the 'device' nodes of a given type from the config.
+
+        name   device type
+        return list of device configs
+        """
+        devices = []
+        for d in sxp.children(self.config, 'device'):
+            dev = sxp.child0(d)
+            if dev is None: continue
+            if name == sxp.name(dev):
+                devices.append(dev)
+        return devices
+
+    def add_device(self, type, dev):
+        """Add a device to a virtual machine.
+
+        dev      device to add
+        """
+        dl = self.devices.get(type, [])
+        dl.append(dev)
+        self.devices[type] = dl
+
+    def get_devices(self, type):
+        val = self.devices.get(type, [])
+        return val
+
+    def get_device_by_id(self, type, id):
+        """Get the device with the given id.
+
+        id       device id
+
+        returns  device or None
+        """
+        dl = self.get_devices(type)
+        for d in dl:
+            if d.getprop('id') == id:
+                return d
+        return None
+
+    def get_device_by_index(self, type, idx):
+        """Get the device with the given index.
+
+        idx       device index
+
+        returns  device or None
+        """
+        dl = self.get_devices(type)
+        if 0 <= idx < len(dl):
+            return dl[idx]
+        else:
+            return None
+
+    def add_config(self, val):
+        """Add configuration data to a virtual machine.
+
+        val      data to add
+        """
+        self.configs.append(val)
+
+    def destroy(self):
+        if self.dom <= 0:
+            return 0
+        return xc.domain_destroy(dom=self.dom)
+
+    def died(self):
+        print 'died>', self.dom
+        self.release_devices()
+
+    def release_devices(self):
+        print 'release_devices>', self.dom
+        self.release_vifs()
+        self.release_vbds()
+        self.devices = {}
+
+    def release_vifs(self):
+        print 'release_vifs>', self.dom
+        if self.dom is None: return
+        ctrl = xend.netif_get(self.dom)
+        if ctrl:
+            ctrl.destroy()
+
+    def release_vbds(self):
+        print 'release_vbds>', self.dom
+        if self.dom is None: return
+        ctrl = xend.blkif_get(self.dom)
+        if ctrl:
+            ctrl.destroy()
+
+    def show(self):
+        """Print virtual machine info.
+        """
+        print "[VM dom=%d name=%s memory=%d" % (self.dom, self.name, self.memory)
+        print "image:"
+        sxp.show(self.image)
+        print
+        for dl in self.devices:
+            for dev in dl:
+                print "device:"
+                sxp.show(dev)
+                print
+        for val in self.configs:
+            print "config:"
+            sxp.show(val)
+            print
+        print "]"
+
+    def init_domain(self):
+        """Initialize the domain memory.
+        """
+        if self.recreate: return
+        memory = self.memory
+        name = self.name
+        cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
+        print 'init_domain>', memory, name, cpu
+        dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
+        if dom <= 0:
+            raise VmError('Creating domain failed: name=%s memory=%d'
+                          % (name, memory))
+        self.setdom(dom)
+
+    def build_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
+        """Build the domain boot image.
+        """
+        if self.recreate: return
+        if len(cmdline) >= 256:
+            print 'Warning: kernel cmdline too long'
+        dom = self.dom
+        buildfn = getattr(xc, '%s_build' % ostype)
+        print 'build_domain>', ostype, dom, kernel, cmdline, ramdisk
+        flags = 0
+        if self.netif_backend: flags |= SIF_NET_BE_DOMAIN
+        if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN
+        err = buildfn(dom            = dom,
+                      image          = kernel,
+                      control_evtchn = self.console.port2,
+                      cmdline        = cmdline,
+                      ramdisk        = ramdisk,
+                      flags          = flags)
+        if err != 0:
+            raise VmError('Building domain failed: type=%s dom=%d err=%d'
+                          % (ostype, dom, err))
+
+    def create_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
+        """Create a domain. Builds the image but does not configure it.
+
+        ostype  OS type
+        kernel  kernel image
+        ramdisk kernel ramdisk
+        cmdline kernel commandline
+        vifs_n  number of network interfaces
+        """
+        print 'create_domain>', ostype, kernel
+        if not self.recreate:
+            if not os.path.isfile(kernel):
+                raise VmError('Kernel image does not exist: %s' % kernel)
+            if ramdisk and not os.path.isfile(ramdisk):
+                raise VMError('Kernel ramdisk does not exist: %s' % ramdisk)
+        print 'create-domain> init_domain...'
+        self.init_domain()
+        print 'create_domain>', 'dom=', self.dom
+        self.console = xendConsole.console_create(self.dom)
+        self.build_domain(ostype, kernel, ramdisk, cmdline, vifs_n)
+        self.image = kernel
+        self.ramdisk = ramdisk
+        self.cmdline = cmdline
+
+    def create_devices(self):
+        """Create the devices for a vm.
+
+        returns Deferred
+        raises VmError for invalid devices
+        """
+        print '>create_devices'
+        dlist = []
+        devices = sxp.children(self.config, 'device')
+        index = {}
+        for d in devices:
+            dev = sxp.child0(d)
+            if dev is None:
+                raise VmError('invalid device')
+            dev_name = sxp.name(dev)
+            dev_index = index.get(dev_name, 0)
+            dev_handler = get_device_handler(dev_name)
+            if dev_handler is None:
+                raise VmError('unknown device type: ' + dev_name)
+            v = dev_handler(self, dev, dev_index)
+            append_deferred(dlist, v)
+            index[dev_name] = dev_index + 1
+        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
+        print '<create_devices'
+        return deferred
+
+    def configure_backends(self):
+        """Set configuration flags if the vm is a backend for netif of blkif.
+        """
+        for c in sxp.children(self.config, 'backend'):
+            name = sxp.name(sxp.child0(c))
+            if name == 'blkif':
+                self.blkif_backend = 1
+            elif name == 'netif':
+                self.netif_backend = 1
+            else:
+                raise VmError('invalid backend type:' + str(name))
+
+    def create_backends(self):
+        """Setup the netif and blkif backends.
+        """
+        if self.blkif_backend:
+            xend.blkif_set_control_domain(self.dom, recreate=self.recreate)
+        if self.netif_backend:
+            xend.netif_set_control_domain(self.dom, recreate=self.recreate)
+            
+    def configure(self):
+        """Configure a vm.
+
+        vm         virtual machine
+        config     configuration
+
+        returns Deferred - calls callback with vm
+        """
+        if self.blkif_backend:
+            d = defer.Deferred()
+            d.callback(1)
+        else:
+            d = xend.blkif_create(self.dom, recreate=self.recreate)
+        d.addCallback(_vm_configure1, self)
+        return d
+
+    def dom_configure(self, dom):
+        """Configure a domain.
+
+        dom    domain id
+        returns deferred
+        """
+        d = dom_get(dom)
+        if not d:
+            raise VMError("Domain not found: %d" % dom)
+        try:
+            self.setdom(dom)
+            self.name = d['name']
+            self.memory = d['memory']/1024
+            deferred = self.configure()
+        except StandardError, ex:
+            self.destroy()
+            raise
+        return deferred
+
+    def configure_fields(self):
+        dlist = []
+        index = {}
+        for field in sxp.children(self.config):
+            field_name = sxp.name(field)
+            field_index = index.get(field_name, 0)
+            field_handler = get_config_handler(field_name)
+            # Ignore unknown fields. Warn?
+            if field_handler:
+                v = field_handler(self, self.config, field, field_index)
+                append_deferred(dlist, v)
+            index[field_name] = field_index + 1
+        d = defer.DeferredList(dlist, fireOnOneErrback=1)
+        return d
+
+
+def vm_image_linux(vm, image):
+    """Create a VM for a linux image.
+
+    name      vm name
+    memory    vm memory
+    image     image config
+
+    returns vm
+    """
+    kernel = sxp.child_value(image, "kernel")
+    cmdline = ""
+    ip = sxp.child_value(image, "ip", "dhcp")
+    if ip:
+        cmdline += " ip=" + ip
+    root = sxp.child_value(image, "root")
+    if root:
+        cmdline += " root=" + root
+    args = sxp.child_value(image, "args")
+    if args:
+        cmdline += " " + args
+    ramdisk = sxp.child_value(image, "ramdisk", '')
+    vifs = vm.config_devices("vif")
+    vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs))
+    return vm
+
+def vm_image_netbsd(vm, image):
+    """Create a VM for a bsd image.
+
+    name      vm name
+    memory    vm memory
+    image     image config
+
+    returns vm
+    """
+    #todo: Same as for linux. Is that right? If so can unify them.
+    kernel = sxp.child_value(image, "kernel")
+    cmdline = ""
+    ip = sxp.child_value(image, "ip", "dhcp")
+    if ip:
+        cmdline += "ip=" + ip
+    root = sxp.child_value(image, "root")
+    if root:
+        cmdline += "root=" + root
+    args = sxp.child_value(image, "args")
+    if args:
+        cmdline += " " + args
+    ramdisk = sxp.child_value(image, "ramdisk")
+    vifs = vm.config_devices("vif")
+    vm.create_domain("netbsd", kernel, ramdisk, cmdline, len(vifs))
+    return vm
+
+
+def vm_dev_vif(vm, val, index):
+    """Create a virtual network interface (vif).
+
+    vm        virtual machine
+    val       vif config
+    index     vif index
+    """
+    if vm.netif_backend:
+        raise VmError('vif: vif in netif backend domain')
+    vif = index #todo
+    vmac = sxp.child_value(val, "mac")
+    defer = make_vif(vm.dom, vif, vmac, vm.recreate)
+    def fn(id):
+        dev = xend.netif_dev(vm.dom, vif)
+        devid = sxp.attribute(val, 'id')
+        if devid:
+            dev.setprop('id', devid)
+        bridge = sxp.child_value(val, "bridge")
+        dev.up(bridge)
+        vm.add_device('vif', dev)
+        print 'vm_dev_vif> created', dev
+        return id
+    defer.addCallback(fn)
+    return defer
+
+def vm_dev_vbd(vm, val, index):
+    """Create a virtual block device (vbd).
+
+    vm        virtual machine
+    val       vbd config
+    index     vbd index
+    """
+    if vm.blkif_backend:
+        raise VmError('vbd: vbd in blkif backend domain')
+    vdev = index
+    uname = sxp.child_value(val, 'uname')
+    if not uname:
+        raise VMError('vbd: Missing uname')
+    dev = sxp.child_value(val, 'dev')
+    if not dev:
+        raise VMError('vbd: Missing dev')
+    mode = sxp.child_value(val, 'mode', 'r')
+    defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
+    def fn(vbd):
+        dev = xend.blkif_dev(vm.dom, vdev)
+        vm.add_device('vbd', dev)
+        return vbd
+    defer.addCallback(fn)
+    return defer
+
+def parse_pci(val):
+    if isinstance(val, StringType):
+        radix = 10
+        if val.startswith('0x') or val.startswith('0X'):
+            radix = 16
+        v = int(val, radix)
+    else:
+        v = val
+    return v
+
+def vm_dev_pci(vm, val, index):
+    bus = sxp.child_value(val, 'bus')
+    if not bus:
+        raise VMError('pci: Missing bus')
+    dev = sxp.child_value(val, 'dev')
+    if not dev:
+        raise VMError('pci: Missing dev')
+    func = sxp.child_value(val, 'func')
+    if not func:
+        raise VMError('pci: Missing func')
+    try:
+        bus = parse_pci(bus)
+        dev = parse_pci(dev)
+        func = parse_pci(func)
+    except:
+        raise VMError('pci: invalid parameter')
+    rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev,
+                                      func=func, enable=1)
+    if rc < 0:
+        #todo non-fatal
+        raise VMError('pci: Failed to configure device: bus=%s dev=%s func=%s' %
+                      (bus, dev, func))
+    return rc
+    
+
+def vm_field_vfr(vm, config, val, index):
+    """Handle a vfr field in a config.
+
+    vm        virtual machine
+    config    vm config
+    val       vfr field
+    """
+    # Get the rules and add them.
+    # (vfr (vif (id foo) (ip x.x.x.x)) ... ) 
+    list = sxp.children(val, 'vif')
+    ipaddrs = []
+    for v in list:
+        id = sxp.child_value(v, 'id')
+        if id is None:
+            raise VmError('vfr: missing vif id')
+        id = int(id)
+        dev = vm.get_device_by_index('vif', id)
+        if not dev:
+            raise VmError('vfr: invalid vif id %d' % id)
+        vif = sxp.child_value(dev, 'vif')
+        ip = sxp.child_value(v, 'ip')
+        if not ip:
+            raise VmError('vfr: missing ip address')
+        ipaddrs.append(ip);
+        # todo: Configure the ipaddrs.
+    vm.ipaddrs = ipaddrs
+
+def vnet_bridge(vnet, vmac, dom, idx):
+    """Add the device for the vif to the bridge for its vnet.
+    """
+    vif = "vif%d.%d" % (dom, idx)
+    try:
+        cmd = "(vif.conn (vif %s) (vnet %s) (vmac %s))" % (vif, vnet, vmac)
+        print "*** vnet_bridge>", cmd
+        out = file("/proc/vnet/policy", "wb")
+        out.write(cmd)
+        err = out.close()
+        print "vnet_bridge>", "err=", err
+    except IOError, ex:
+        print "vnet_bridge>", ex
+    
+def vm_field_vnet(vm, config, val, index):
+    """Handle a vnet field in a config.
+
+    vm        virtual machine
+    config    vm config
+    val       vnet field
+    index     index
+    """
+    # Get the vif children. For each vif look up the vif device
+    # with the given id and configure its vnet.
+    # (vnet (vif (id foo) (vnet 2) (mac x:x:x:x:x:x)) ... )
+    vif_vnets = sxp.children(val, 'vif')
+    for v in vif_vnets:
+        id = sxp.child_value(v, 'id')
+        if id is None:
+            raise VmError('vnet: missing vif id')
+        dev = vm.get_device_by_id('vif', id)
+        #vnet = sxp.child_value(v, 'vnet', 1)
+        #mac = sxp.child_value(dev, 'mac')
+        #vif = sxp.child_value(dev, 'vif')
+        #vnet_bridge(vnet, mac, vm.dom, 0)
+        #vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]])
+
+# Register image handlers for linux and bsd.
+add_image_handler('linux',  vm_image_linux)
+add_image_handler('netbsd', vm_image_netbsd)
+
+# Register device handlers for vifs and vbds.
+add_device_handler('vif',  vm_dev_vif)
+add_device_handler('vbd',  vm_dev_vbd)
+add_device_handler('pci',  vm_dev_pci)
+
+# Register config handlers for vfr and vnet.
+add_config_handler('vfr',  vm_field_vfr)
+add_config_handler('vnet', vm_field_vnet)
diff --git a/tools/python/xen/xend/XendMigrate.py b/tools/python/xen/xend/XendMigrate.py
new file mode 100644 (file)
index 0000000..1580ba8
--- /dev/null
@@ -0,0 +1,103 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+import sys
+import socket
+
+import sxp
+import XendDB
+import EventServer; eserver = EventServer.instance()
+
+class XendMigrateInfo:
+
+    # states: begin, active, failed, succeeded?
+
+    def __init__(self, id, dom, dst):
+        self.id = id
+        self.state = 'begin'
+        self.src_host = socket.gethostname()
+        self.src_dom = dom
+        self.dst_host = dst
+        self.dst_dom = None
+        
+    def set_state(self, state):
+        self.state = state
+
+    def get_state(self):
+        return self.state
+
+    def sxpr(self):
+        sxpr = ['migrate', ['id', self.id], ['state', self.state] ]
+        sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ]
+        sxpr.append(sxpr_src)
+        sxpr_dst = ['dst', ['host', self.dst] ]
+        if self.dst_dom:
+            sxpr_dst.append(['domain', self.dst_dom])
+        sxpr.append(sxpr_dst)
+        return sxpr
+    
+
+class XendMigrate:
+    # Represents migration in progress.
+    # Use log for indications of begin/end/errors?
+    # Need logging of: domain create/halt, migrate begin/end/fail
+    # Log via event server?
+
+    dbpath = "migrate"
+    
+    def __init__(self):
+        self.db = XendDB.XendDB(self.dbpath)
+        self.migrate = {}
+        self.migrate_db = self.db.fetchall("")
+        self.id = 0
+
+    def nextid(self):
+        self.id += 1
+        return "%d" % self.id
+
+    def sync(self):
+        self.db.saveall("", self.migrate_db)
+
+    def sync_migrate(self, id):
+        self.db.save(id, self.migrate_db[id])
+
+    def close(self):
+        pass
+
+    def _add_migrate(self, id, info):
+        self.migrate[id] = info
+        self.migrate_db[id] = info.sxpr()
+        self.sync_migrate(id)
+        #eserver.inject('xend.migrate.begin', info.sxpr())
+
+    def _delete_migrate(self, id):
+        #eserver.inject('xend.migrate.end', id)
+        del self.migrate[id]
+        del self.migrate_db[id]
+        self.db.delete(id)
+
+    def migrate_ls(self):
+        return self.migrate.keys()
+
+    def migrates(self):
+        return self.migrate.values()
+
+    def migrate_get(self, id):
+        return self.migrate.get(id)
+    
+    def migrate_begin(self, dom, dst):
+        # Check dom for existence, not migrating already.
+        # Create migrate info, tell xend to migrate it?
+        # - or fork migrate command ourselves?
+        # Subscribe to migrate notifications (for updating).
+        id = self.nextid()
+        info = XenMigrateInfo(id, dom, dst)
+        self._add_migrate(id, info)
+        return id
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendMigrate()
+    return inst
diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py
new file mode 100644 (file)
index 0000000..7221785
--- /dev/null
@@ -0,0 +1,71 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Handler for node operations.
+ Has some persistent state:
+ - logs
+ - notification urls
+
+"""
+
+import os
+import xen.ext.xc
+
+class XendNode:
+
+    def __init__(self):
+        self.xc = xen.ext.xc.new()
+
+    def shutdown(self):
+        return 0
+
+    def reboot(self):
+        return 0
+
+    def notify(self, uri):
+        return 0
+    
+    def cpu_bvt_slice_set(self, slice):
+        ret = 0
+        #ret = self.xc.bvtsched_global_set(ctx_allow=slice)
+        return ret
+
+    def cpu_bvt_slice_get(self, slice):
+        ret = 0
+        #ret = self.xc.bvtsched_global_get()
+        return ret
+    
+    def cpu_rrobin_slice_set(self, slice):
+        ret = 0
+        #ret = self.xc.rrobin_global_set(slice)
+        return ret
+
+    def info(self):
+        return self.nodeinfo() + self.physinfo()
+
+    def nodeinfo(self):
+        (sys, host, rel, ver, mch) = os.uname()
+        return [['system',  sys],
+                ['host',    host],
+                ['release', rel],
+                ['version', ver],
+                ['machine', mch]]
+
+    def physinfo(self):
+        pinfo = self.xc.physinfo()
+        info = [['cores', pinfo['cores']],
+                ['hyperthreads_per_core', pinfo['ht_per_core']],
+                ['cpu_mhz', pinfo['cpu_khz']/1000],
+                ['memory', pinfo['total_pages']/256],
+                ['free_memory', pinfo['free_pages']/256]]
+        return info
+        
+        
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendNode()
+    return inst
+
diff --git a/tools/python/xen/xend/XendRoot.py b/tools/python/xen/xend/XendRoot.py
new file mode 100644 (file)
index 0000000..665f5df
--- /dev/null
@@ -0,0 +1,156 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Xend root class.
+Creates the event server and handles configuration.
+"""
+
+import os
+import os.path
+import sys
+import EventServer
+
+# Initial create of the event server.
+eserver = EventServer.instance()
+
+import sxp
+
+def reboots():
+    """Get a list of system reboots from wtmp.
+    """
+    out = os.popen('/usr/bin/last reboot', 'r')
+    list = [ x.strip() for x in out if x.startswith('reboot') ]
+    return list
+
+def last_reboot():
+    """Get the last known system reboot.
+    """
+    l = reboots()
+    return (l and l[-1]) or None
+
+class XendRoot:
+    """Root of the management classes."""
+
+    lastboot_default = "/var/xen/lastboot"
+
+    """Default path to the root of the database."""
+    dbroot_default = "/var/xen/xend-db"
+
+    """Default path to the config file."""
+    config_default = "/etc/xen/xend-config.sxp"
+
+    """Environment variable used to override config_default."""
+    config_var     = "XEND_CONFIG"
+
+    def __init__(self):
+        self.rebooted = 0
+        self.last_reboot = None
+        self.dbroot = None
+        self.config_path = None
+        self.config = None
+        self.configure()
+        self.check_lastboot()
+        eserver.subscribe('xend.*', self.event_handler)
+        #eserver.subscribe('xend.domain.created', self.event_handler)
+        #eserver.subscribe('xend.domain.died', self.event_handler)
+
+    def start(self):
+        eserver.inject('xend.start', self.rebooted)
+
+    def event_handler(self, event, val):
+        print >> sys.stderr, "EVENT>", event, val
+
+    def read_lastboot(self):
+        try:
+            val = file(self.lastboot, 'rb').readlines()[0]
+        except StandardError, ex:
+            print 'warning: Error reading', self.lastboot, ex
+            val = None
+        return val
+
+    def write_lastboot(self, val):
+        if not val: return
+        try:
+            fdir = os.path.dirname(self.lastboot)
+            if not os.path.isdir(fdir):
+                os.makedirs(fdir)
+            out = file(self.lastboot, 'wb+')
+            out.write(val)
+            out.close()
+        except IOError, ex:
+            print 'warning: Error writing', self.lastboot, ex
+            pass
+
+    def check_lastboot(self):
+        """Check if there has been a system reboot since we saved lastboot.
+        """
+        last_val = self.read_lastboot()
+        this_val = last_reboot()
+        if this_val == last_val:
+            self.rebooted = 0
+        else:
+            self.rebooted = 1
+            self.write_lastboot(this_val)
+        self.last_reboot = this_val
+
+    def get_last_reboot(self):
+        return self.last_reboot
+
+    def get_rebooted(self):
+        return self.rebooted
+
+    def configure(self):
+        self.set_config()
+        self.dbroot = self.get_config_value("dbroot", self.dbroot_default)
+        self.lastboot = self.get_config_value("lastboot", self.lastboot_default)
+
+    def get_dbroot(self):
+        """Get the path to the database root.
+        """
+        return self.dbroot
+
+    def set_config(self):
+        """If the config file exists, read it. If not, ignore it.
+
+        The config file is a sequence of sxp forms.
+        """
+        self.config_path = os.getenv(self.config_var, self.config_default)
+        if os.path.exists(self.config_path):
+            fin = file(self.config_path, 'rb')
+            try:
+                config = sxp.parse(fin)
+                config.insert(0, 'config')
+                self.config = config
+            finally:
+                fin.close()
+        else:
+            self.config = ['config']
+
+    def get_config(self, name=None):
+        """Get the configuration element with the given name, or
+        the whole configuration if no name is given.
+
+        name   element name (optional)
+        returns config or none
+        """
+        if name is None:
+            val = self.config
+        else:
+            val = sxp.child(self.config, name)
+        return val
+
+    def get_config_value(self, name, val=None):
+        """Get the value of an atomic configuration element.
+
+        name   element name
+        val    default value (optional, defaults to None)
+        returns value
+        """
+        return sxp.child_value(self.config, name, val=val)
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendRoot()
+    return inst
diff --git a/tools/python/xen/xend/XendVnet.py b/tools/python/xen/xend/XendVnet.py
new file mode 100644 (file)
index 0000000..213408e
--- /dev/null
@@ -0,0 +1,69 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Handler for vnet operations.
+"""
+
+import sxp
+import XendDB
+
+class XendVnet:
+    """Index of all vnets. Singleton.
+    """
+
+    dbpath = "vnet"
+
+    def __init__(self):
+        # Table of vnet info indexed by vnet id.
+        self.vnet = {}
+        self.db = XendDB.XendDB(self.dbpath)
+        self.vnet = self.db.fetchall("")
+
+    def vnet_ls(self):
+        """List all vnets.
+        """
+        return self.vnet.keys()
+
+    def vnets(self):
+        return self.vnet.values()
+
+    def vnet_get(self, id):
+        """Get a vnet.
+
+        id     vnet id
+        """
+        return self.vnet.get(id)
+
+    def vnet_create(self, info):
+        """Create a vnet.
+
+        info   config
+        """
+        self.vnet_configure(info)
+
+    def vnet_configure(self, info):
+        """Configure a vnet.
+        id     vnet id
+        info   config
+        """
+        # Need to configure for real.
+        # Only sync if succeeded - otherwise need to back out.
+        self.vnet[info.id] = info
+        self.db.save(info.id, info)
+
+    def vnet_delete(self, id):
+        """Delete a vnet.
+
+        id     vnet id
+        """
+        # Need to delete for real. What if fails?
+        if id in self.vnet:
+            del self.vnet[id]
+            self.db.delete(id)
+
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = XendVnet()
+    return inst
diff --git a/tools/python/xen/xend/__init__.py b/tools/python/xen/xend/__init__.py
new file mode 100644 (file)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/tools/python/xen/xend/encode.py b/tools/python/xen/xend/encode.py
new file mode 100644 (file)
index 0000000..38c9351
--- /dev/null
@@ -0,0 +1,165 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Encoding for arguments to HTTP calls.
+   Uses the url-encoding with MIME type 'application/x-www-form-urlencoded'
+   if the data does not include files. Otherwise it uses the encoding with
+   MIME type 'multipart/form-data'. See the HTML4 spec for details.
+
+   """
+import sys
+import types
+from StringIO import StringIO
+
+import urllib
+import httplib
+import random
+import md5
+
+# Extract from HTML4 spec.
+## The following example illustrates "multipart/form-data"
+## encoding. Suppose we have the following form:
+
+##  <FORM action="http://server.com/cgi/handle"
+##        enctype="multipart/form-data"
+##        method="post">
+##    <P>
+##    What is your name? <INPUT type="text" name="submit-name"><BR>
+##    What files are you sending? <INPUT type="file" name="files"><BR>
+##    <INPUT type="submit" value="Send"> <INPUT type="reset">
+##  </FORM>
+
+## If the user enters "Larry" in the text input, and selects the text
+## file "file1.txt", the user agent might send back the following data:
+
+##    Content-Type: multipart/form-data; boundary=AaB03x
+
+##    --AaB03x
+##    Content-Disposition: form-data; name="submit-name"
+
+##    Larry
+##    --AaB03x
+##    Content-Disposition: form-data; name="files"; filename="file1.txt"
+##    Content-Type: text/plain
+
+##    ... contents of file1.txt ...
+##    --AaB03x--
+
+## If the user selected a second (image) file "file2.gif", the user agent
+## might construct the parts as follows:
+
+##    Content-Type: multipart/form-data; boundary=AaB03x
+
+##    --AaB03x
+##    Content-Disposition: form-data; name="submit-name"
+
+##    Larry
+##    --AaB03x
+##    Content-Disposition: form-data; name="files"
+##    Content-Type: multipart/mixed; boundary=BbC04y
+
+##    --BbC04y
+##    Content-Disposition: file; filename="file1.txt"
+##    Content-Type: text/plain
+
+##    ... contents of file1.txt ...
+##    --BbC04y
+##    Content-Disposition: file; filename="file2.gif"
+##    Content-Type: image/gif
+##    Content-Transfer-Encoding: binary
+
+##    ...contents of file2.gif...
+##    --BbC04y--
+##    --AaB03x--
+
+__all__ = ['encode_data', 'encode_multipart', 'encode_form', 'mime_boundary' ]
+
+def data_values(d):
+    if isinstance(d, types.DictType):
+        return d.items()
+    else:
+        return d
+
+def encode_data(d):
+    """Encode some data for HTTP transport.
+    The encoding used is stored in 'Content-Type' in the headers.
+
+    d  data - sequence of tuples or dictionary
+    returns a 2-tuple of the headers and the encoded data
+    """
+    val = ({}, None)
+    if d is None: return val
+    multipart = 0
+    for (k, v) in data_values(d):
+        if encode_isfile(v):
+            multipart = 1
+            break
+    if multipart:
+        val = encode_multipart(d)
+    else:
+        val = encode_form(d)
+    return val
+
+def encode_isfile(v):
+    if isinstance(v, types.FileType):
+        return 1
+    if hasattr(v, 'readlines'):
+        return 1
+    return 0
+
+def encode_multipart(d):
+    boundary = mime_boundary()
+    hdr = { 'Content-Type': 'multipart/form-data; boundary=' + boundary }
+    out = StringIO()
+    for (k,v) in data_values(d):
+        out.write('--')
+        out.write(boundary)
+        out.write('\r\n')
+        if encode_isfile(v):
+            out.write('Content-Disposition: form-data; name="')
+            out.write(k)
+            if hasattr(v, 'name'):
+                out.write('"; filename="')
+                out.write(v.name)
+            out.write('"\r\n')
+            out.write('Content-Type: application/octet-stream\r\n')
+            out.write('\r\n')
+            for l in v.readlines():
+               out.write(l)  
+        else:
+            out.write('Content-Disposition: form-data; name="')
+            out.write(k)
+            out.write('"\r\n')
+            out.write('\r\n')
+            out.write(str(v))
+            out.write('\r\n')
+    out.write('--')
+    out.write(boundary)
+    out.write('--')
+    out.write('\r\n')
+    return (hdr, out.getvalue())
+
+def mime_boundary():
+    random.seed()
+    m = md5.new()
+    for i in range(0, 10):
+        c = chr(random.randint(1, 255))
+        m.update(c)
+    b = m.hexdigest()
+    return b[0:16]
+
+def encode_form(d):
+    hdr = { 'Content-Type': 'application/x-www-form-urlencoded' }
+    val = urllib.urlencode(d)
+    return (hdr, val)
+
+def main():
+    #d = {'a': 1, 'b': 'x y', 'c': file('conf.sxp') }
+    #d = {'a': 1, 'b': 'x y' }
+    d = [ ('a', 1), ('b', 'x y'), ('c', file('conf.sxp')) ]
+    #d = [ ('a', 1), ('b', 'x y')]
+    v = encode_data(d)
+    print v[0]
+    sys.stdout.write(v[1])
+    print
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/python/xen/xend/server/SrvBase.py b/tools/python/xen/xend/server/SrvBase.py
new file mode 100644 (file)
index 0000000..bcff1bc
--- /dev/null
@@ -0,0 +1,137 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+import cgi
+
+import os
+import sys
+import types
+import StringIO
+
+from twisted.internet import defer
+from twisted.internet import reactor
+from twisted.web import error
+from twisted.web import resource
+from twisted.web import server
+
+from xen.xend import sxp
+from xen.xend import PrettyPrint
+
+def uri_pathlist(p):
+    """Split a path into a list.
+    p          path
+    return list of path elements
+    """
+    l = []
+    for x in p.split('/'):
+        if x == '': continue
+        l.append(x)
+    return l
+
+class SrvBase(resource.Resource):
+    """Base class for services.
+    """
+
+    def parse_form(self, req, method):
+        """Parse the data for a request, GET using the URL, POST using encoded data.
+        Posts should use enctype='multipart/form-data' in the <form> tag,
+        rather than 'application/x-www-form-urlencoded'. Only 'multipart/form-data'
+        handles file upload.
+
+        req            request
+        returns a cgi.FieldStorage instance
+        """
+        env = {}
+        env['REQUEST_METHOD'] = method
+        if self.query:
+            env['QUERY_STRING'] = self.query
+        val = cgi.FieldStorage(fp=req.rfile, headers=req.headers, environ=env)
+        return val
+    
+    def use_sxp(self, req):
+        """Determine whether to send an SXP response to a request.
+        Uses SXP if there is no User-Agent, no Accept, or application/sxp is in Accept.
+
+        req            request
+        returns 1 for SXP, 0 otherwise
+        """
+        ok = 0
+        user_agent = req.getHeader('User-Agent')
+        accept = req.getHeader('Accept')
+        if (not user_agent) or (not accept) or (accept.find(sxp.mime_type) >= 0):
+            ok = 1
+        return ok
+
+    def get_op_method(self, op):
+        """Get the method for an operation.
+        For operation 'foo' looks for 'op_foo'.
+
+        op     operation name
+        returns method or None
+        """
+        op_method_name = 'op_' + op
+        return getattr(self, op_method_name, None)
+        
+    def perform(self, req):
+        """General operation handler for posted operations.
+        For operation 'foo' looks for a method op_foo and calls
+        it with op_foo(op, req). Replies with code 500 if op_foo
+        is not found.
+
+        The method must return a list when req.use_sxp is true
+        and an HTML string otherwise (or list).
+        Methods may also return a Deferred (for incomplete processing).
+
+        req    request
+        """
+        op = req.args.get('op')
+        if op is None or len(op) != 1:
+            req.setResponseCode(404, "Invalid")
+            return ''
+        op = op[0]
+        op_method = self.get_op_method(op)
+        if op_method is None:
+            req.setResponseCode(501, "Not implemented")
+            req.setHeader("Content-Type", "text/plain")
+            req.write("Not implemented: " + op)
+            return ''
+        else:
+            val = op_method(op, req)
+            if isinstance(val, defer.Deferred):
+                val.addCallback(self._cb_perform, req, 1)
+                return server.NOT_DONE_YET
+            else:
+                self._cb_perform(val, req, 0)
+                return ''
+
+    def _cb_perform(self, val, req, dfr):
+        """Callback to complete the request.
+        May be called from a Deferred.
+        """
+        if isinstance(val, error.ErrorPage):
+            req.write(val.render(req))
+        elif self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            sxp.show(val, req)
+        else:
+            req.write('<html><head></head><body>')
+            self.print_path(req)
+            if isinstance(val, types.ListType):
+                req.write('<code><pre>')
+                PrettyPrint.prettyprint(val, out=req)
+                req.write('</pre></code>')
+            else:
+                req.write(str(val))
+            req.write('</body></html>')
+        if dfr:
+            req.finish()
+
+    def print_path(self, req):
+        """Print the path with hyperlinks.
+        """
+        pathlist = [x for x in req.prepath if x != '' ]
+        s = "/"
+        req.write('<h1><a href="/">/</a>')
+        for x in pathlist:
+            s += x + "/"
+            req.write(' <a href="%s">%s</a>/' % (s, x))
+        req.write("</h1>")
diff --git a/tools/python/xen/xend/server/SrvConsole.py b/tools/python/xen/xend/server/SrvConsole.py
new file mode 100644 (file)
index 0000000..59d0e5f
--- /dev/null
@@ -0,0 +1,42 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from xen.xend import sxp
+from xen.xend import XendConsole
+from SrvDir import SrvDir
+
+class SrvConsole(SrvDir):
+    """An individual console.
+    """
+
+    def __init__(self, info):
+        SrvDir.__init__(self)
+        self.info = info
+        self.xc = XendConsole.instance()
+
+    def op_disconnect(self, op, req):
+        val = self.xc.console_disconnect(self.info.id)
+        return val
+
+    def render_POST(self, req):
+        return self.perform(req)
+        
+    def render_GET(self, req):
+        if self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            sxp.show(self.info.sxpr(), out=req)
+        else:
+            req.write('<html><head></head><body>')
+            self.print_path(req)
+            #self.ls()
+            req.write('<p>%s</p>' % self.info)
+            req.write('<p><a href="%s">Connect to domain %d</a></p>'
+                      % (self.info.uri(), self.info.dom2))
+            self.form(req)
+            req.write('</body></html>')
+        return ''
+
+    def form(self, req):
+        req.write('<form method="post" action="%s">' % req.prePathURL())
+        if self.info.connection():
+            req.write('<input type="submit" name="op" value="disconnect">')
+        req.write('</form>')
diff --git a/tools/python/xen/xend/server/SrvConsoleDir.py b/tools/python/xen/xend/server/SrvConsoleDir.py
new file mode 100644 (file)
index 0000000..814b448
--- /dev/null
@@ -0,0 +1,59 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from SrvDir import SrvDir
+from SrvConsole import SrvConsole
+from xen.xend import XendConsole
+from xen.xend import sxp
+
+class SrvConsoleDir(SrvDir):
+    """Console directory.
+    """
+
+    def __init__(self):
+        SrvDir.__init__(self)
+        self.xconsole = XendConsole.instance()
+
+    def console(self, x):
+        val = None
+        try:
+            info = self.xconsole.console_get(x)
+            val = SrvConsole(info)
+        except KeyError, ex:
+            print 'SrvConsoleDir>', ex
+            pass
+        return val
+
+    def get(self, x):
+        v = SrvDir.get(self, x)
+        if v is not None:
+            return v
+        v = self.console(x)
+        return v
+
+    def render_GET(self, req):
+        if self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            self.ls_console(req, 1)
+        else:
+            req.write("<html><head></head><body>")
+            self.print_path(req)
+            self.ls(req)
+            self.ls_console(req)
+            #self.form(req.wfile)
+            req.write("</body></html>")
+        return ''
+
+    def ls_console(self, req, use_sxp=0):
+        url = req.prePathURL()
+        if not url.endswith('/'):
+            url += '/'
+        if use_sxp:
+            consoles = self.xconsole.console_ls()
+            sxp.show(consoles, out=req)
+        else:
+            consoles = self.xconsole.consoles()
+            consoles.sort(lambda x, y: cmp(x.id, y.id))
+            req.write('<ul>')
+            for c in consoles:
+                req.write('<li><a href="%s%s"> %s</a></li>' % (url, c.id, c))
+            req.write('</ul>')
diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py
new file mode 100644 (file)
index 0000000..c8284dc
--- /dev/null
@@ -0,0 +1,751 @@
+###########################################################
+## Xen controller daemon
+## Copyright (c) 2004, K A Fraser (University of Cambridge)
+## Copyright (C) 2004, Mike Wray <mike.wray@hp.com>
+###########################################################
+
+import os
+import os.path
+import signal
+import sys
+import threading
+import linecache
+import socket
+import pwd
+import re
+import StringIO
+
+from twisted.internet import pollreactor
+pollreactor.install()
+
+from twisted.internet import reactor
+from twisted.internet import protocol
+from twisted.internet import abstract
+from twisted.internet import defer
+
+from xen.ext import xu
+
+from xen.xend import sxp
+from xen.xend import PrettyPrint
+from xen.xend import EventServer
+eserver = EventServer.instance()
+
+from xen.xend.server import SrvServer
+
+import channel
+import blkif
+import netif
+import console
+import domain
+from params import *
+
+DEBUG = 1
+
+class MgmtProtocol(protocol.DatagramProtocol):
+    """Handler for the management socket (unix-domain).
+    """
+
+    def __init__(self, daemon):
+        #protocol.DatagramProtocol.__init__(self)
+        self.daemon = daemon
+    
+    def write(self, data, addr):
+        return self.transport.write(data, addr)
+
+    def datagramReceived(self, data, addr):
+        if DEBUG: print 'datagramReceived> addr=', addr, 'data=', data
+        io = StringIO.StringIO(data)
+        try:
+            vals = sxp.parse(io)
+            res = self.dispatch(vals[0])
+            self.send_result(addr, res)
+        except SystemExit:
+            raise
+        except:
+            if DEBUG:
+                raise
+            else:
+                self.send_error(addr)
+
+    def send_reply(self, addr, sxpr):
+        io = StringIO.StringIO()
+        sxp.show(sxpr, out=io)
+        io.seek(0)
+        self.write(io.getvalue(), addr)
+
+    def send_result(self, addr, res):
+        
+        def fn(res, self=self, addr=addr):
+            self.send_reply(addr, ['ok', res])
+            
+        if isinstance(res, defer.Deferred):
+            res.addCallback(fn)
+        else:
+            fn(res)
+
+    def send_error(self, addr):
+        (extype, exval) = sys.exc_info()[:2]
+        self.send_reply(addr, ['err',
+                               ['type',  str(extype) ],
+                               ['value', str(exval)  ] ] )
+
+    def opname(self, name):
+        """Get the name of the method for an operation.
+        """
+        return 'op_' + name.replace('.', '_')
+
+    def operror(self, name, v):
+        """Default operation handler - signals an error.
+        """
+        raise NotImplementedError('Invalid operation: ' +name)
+
+    def dispatch(self, req):
+        """Dispatch a request to its handler.
+        """
+        op_name = sxp.name(req)
+        op_method_name = self.opname(op_name)
+        op_method = getattr(self, op_method_name, self.operror)
+        return op_method(op_name, req)
+
+    def op_console_create(self, name, req):
+        """Create a new control interface - console for a domain.
+        """
+        print name, req
+        dom = sxp.child_value(req, 'domain')
+        if not dom: raise ValueError('Missing domain')
+        dom = int(dom)
+        console_port = sxp.child_value(req, 'console_port')
+        if console_port:
+            console_port = int(console_port)
+        resp = self.daemon.console_create(dom, console_port)
+        print name, resp
+        return resp
+
+    def op_consoles(self, name, req):
+        """Get a list of the consoles.
+        """
+        return self.daemon.consoles()
+
+    def op_console_disconnect(self, name, req):
+        id = sxp.child_value(req, 'id')
+        if not id:
+            raise ValueError('Missing console id')
+        id = int(id)
+        console = self.daemon.get_console(id)
+        if not console:
+            raise ValueError('Invalid console id')
+        if console.conn:
+            console.conn.loseConnection()
+        return ['ok']
+
+    def op_blkifs(self, name, req):
+        pass
+    
+    def op_blkif_devs(self, name, req):
+        pass
+
+    def op_blkif_create(self, name, req):
+        pass
+    
+    def op_blkif_dev_create(self, name, req):
+        pass
+
+    def op_netifs(self, name, req):
+        pass
+
+    def op_netif_devs(self, name, req):
+        pass
+
+    def op_netif_create(self, name, req):
+        pass
+
+    def op_netif_dev_create(self, name, req):
+        pass
+
+class NotifierProtocol(protocol.Protocol):
+    """Asynchronous handler for i/o on the notifier (event channel).
+    """
+
+    def __init__(self, channelFactory):
+        self.channelFactory = channelFactory
+
+    def notificationReceived(self, idx, type):
+        #print 'NotifierProtocol>notificationReceived>', idx, type
+        channel = self.channelFactory.getChannel(idx)
+        if not channel:
+            return
+        #print 'NotifierProtocol>notificationReceived> channel', channel
+        channel.notificationReceived(type)
+
+    def connectionLost(self, reason=None):
+        pass
+
+    def doStart(self):
+        pass
+
+    def doStop(self):
+        pass
+
+    def startProtocol(self):
+        pass
+
+    def stopProtocol(self):
+        pass
+
+class NotifierPort(abstract.FileDescriptor):
+    """Transport class for the event channel.
+    """
+
+    def __init__(self, daemon, notifier, proto, reactor=None):
+        assert isinstance(proto, NotifierProtocol)
+        abstract.FileDescriptor.__init__(self, reactor)
+        self.daemon = daemon
+        self.notifier = notifier
+        self.protocol = proto
+
+    def startListening(self):
+        self._bindNotifier()
+        self._connectToProtocol()
+
+    def stopListening(self):
+        if self.connected:
+            result = self.d = defer.Deferred()
+        else:
+            result = None
+        self.loseConnection()
+        return result
+
+    def fileno(self):
+        return self.notifier.fileno()
+
+    def _bindNotifier(self):
+        self.connected = 1
+
+    def _connectToProtocol(self):
+        self.protocol.makeConnection(self)
+        self.startReading()
+
+    def loseConnection(self):
+        if self.connected:
+            self.stopReading()
+            self.disconnecting = 1
+            reactor.callLater(0, self.connectionLost)
+
+    def connectionLost(self, reason=None):
+        abstract.FileDescriptor.connectionLost(self, reason)
+        if hasattr(self, 'protocol'):
+            self.protocol.doStop()
+        self.connected = 0
+        #self.notifier.close() # Not implemented.
+        os.close(self.fileno())
+        del self.notifier
+        if hasattr(self, 'd'):
+            self.d.callback(None)
+            del self.d
+        
+    def doRead(self):
+        #print 'NotifierPort>doRead>', self
+        count = 0
+        while 1:            
+            #print 'NotifierPort>doRead>', count
+            notification = self.notifier.read()
+            if not notification:
+                break
+            (idx, type) = notification
+            self.protocol.notificationReceived(idx, type)
+            self.notifier.unmask(idx)
+            count += 1
+        #print 'NotifierPort>doRead<'
+
+class EventProtocol(protocol.Protocol):
+    """Asynchronous handler for a connected event socket.
+    """
+
+    def __init__(self, daemon):
+        #protocol.Protocol.__init__(self)
+        self.daemon = daemon
+        # Event queue.
+        self.queue = []
+        # Subscribed events.
+        self.events = []
+        self.parser = sxp.Parser()
+        self.pretty = 0
+
+        # For debugging subscribe to everything and make output pretty.
+        self.subscribe(['*'])
+        self.pretty = 1
+
+    def dataReceived(self, data):
+        try:
+            self.parser.input(data)
+            if self.parser.ready():
+                val = self.parser.get_val()
+                res = self.dispatch(val)
+                self.send_result(res)
+            if self.parser.at_eof():
+                self.loseConnection()
+        except SystemExit:
+            raise
+        except:
+            if DEBUG:
+                raise
+            else:
+                self.send_error()
+
+    def loseConnection(self):
+        if self.transport:
+            self.transport.loseConnection()
+        if self.connected:
+            reactor.callLater(0, self.connectionLost)
+
+    def connectionLost(self, reason=None):
+        self.unsubscribe()
+
+    def send_reply(self, sxpr):
+        io = StringIO.StringIO()
+        if self.pretty:
+            PrettyPrint.prettyprint(sxpr, out=io)
+        else:
+            sxp.show(sxpr, out=io)
+        print >> io
+        io.seek(0)
+        return self.transport.write(io.getvalue())
+
+    def send_result(self, res):
+        return self.send_reply(['ok', res])
+
+    def send_error(self):
+        (extype, exval) = sys.exc_info()[:2]
+        return self.send_reply(['err',
+                                ['type', str(extype)],
+                                ['value', str(exval)]])
+
+    def send_event(self, val):
+        return self.send_reply(['event', val[0], val[1]])
+
+    def unsubscribe(self):
+        for event in self.events:
+            eserver.unsubscribe(event, self.queue_event)
+
+    def subscribe(self, events):
+        self.unsubscribe()
+        for event in events:
+            eserver.subscribe(event, self.queue_event)
+        self.events = events
+
+    def queue_event(self, name, v):
+        # Despite the name we dont' queue the event here.
+        # We send it because the transport will queue it.
+        self.send_event([name, v])
+        
+    def opname(self, name):
+         return 'op_' + name.replace('.', '_')
+
+    def operror(self, name, req):
+        raise NotImplementedError('Invalid operation: ' +name)
+
+    def dispatch(self, req):
+        op_name = sxp.name(req)
+        op_method_name = self.opname(op_name)
+        op_method = getattr(self, op_method_name, self.operror)
+        return op_method(op_name, req)
+
+    def op_help(self, name, req):
+        def nameop(x):
+            if x.startswith('op_'):
+                return x[3:].replace('_', '.')
+            else:
+                return x
+        
+        l = [ nameop(k) for k in dir(self) if k.startswith('op_') ]
+        return l
+
+    def op_quit(self, name, req):
+        self.loseConnection()
+
+    def op_exit(self, name, req):
+        sys.exit(0)
+
+    def op_pretty(self, name, req):
+        self.pretty = 1
+        return ['ok']
+
+    def op_console_disconnect(self, name, req):
+        id = sxp.child_value(req, 'id')
+        if not id:
+            raise ValueError('Missing console id')
+        self.daemon.console_disconnect(id)
+        return ['ok']
+
+    def op_info(self, name, req):
+        val = ['info']
+        val += self.daemon.consoles()
+        val += self.daemon.blkifs()
+        val += self.daemon.netifs()
+        return val
+
+    def op_sys_subscribe(self, name, v):
+        # (sys.subscribe event*)
+        # Subscribe to the events:
+        self.subscribe(v[1:])
+        return ['ok']
+
+    def op_sys_inject(self, name, v):
+        # (sys.inject event)
+        event = v[1]
+        eserver.inject(sxp.name(event), event)
+        return ['ok']
+
+
+class EventFactory(protocol.Factory):
+    """Asynchronous handler for the event server socket.
+    """
+    protocol = EventProtocol
+    service = None
+
+    def __init__(self, daemon):
+        #protocol.Factory.__init__(self)
+        self.daemon = daemon
+
+    def buildProtocol(self, addr):
+        proto = self.protocol(self.daemon)
+        proto.factory = self
+        return proto
+
+class VirqClient:
+    def __init__(self, daemon):
+        self.daemon = daemon
+
+    def virqReceived(self, virq):
+        print 'VirqClient.virqReceived>', virq
+        eserver.inject('xend.virq', virq)
+
+    def lostChannel(self, channel):
+        print 'VirqClient.lostChannel>', channel
+        
+class Daemon:
+    """The xend daemon.
+    """
+    def __init__(self):
+        self.shutdown = 0
+
+    def daemon_pids(self):
+        pids = []
+        pidex = '(?P<pid>\d+)'
+        pythonex = '(?P<python>\S*python\S*)'
+        cmdex = '(?P<cmd>.*)'
+        procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
+        xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
+        procs = os.popen('ps -e -o pid,args 2>/dev/null')
+        for proc in procs:
+            pm = procre.match(proc)
+            if not pm: continue
+            xm = xendre.match(pm.group('cmd'))
+            if not xm: continue
+            #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
+            pids.append(int(pm.group('pid')))
+        return pids
+
+    def new_cleanup(self, kill=0):
+        err = 0
+        pids = self.daemon_pids()
+        if kill:
+            for pid in pids:
+                print "Killing daemon pid=%d" % pid
+                os.kill(pid, signal.SIGHUP)
+        elif pids:
+            err = 1
+            print "Daemon already running: ", pids
+        return err
+            
+    def cleanup(self, kill=False):
+        # No cleanup to do if PID_FILE is empty.
+        if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
+            return 0
+        # Read the pid of the previous invocation and search active process list.
+        pid = open(PID_FILE, 'r').read()
+        lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
+        for line in lines:
+            if re.search('^ *' + pid + '.+xend', line):
+                if not kill:
+                    print "Daemon is already running (pid %d)" % int(pid)
+                    return 1
+                # Old daemon is still active: terminate it.
+                os.kill(int(pid), 1)
+        # Delete the stale PID_FILE.
+        os.remove(PID_FILE)
+        return 0
+
+    def install_child_reaper(self):
+        #signal.signal(signal.SIGCHLD, self.onSIGCHLD)
+        # Ensure that zombie children are automatically reaped.
+        xu.autoreap()
+
+    def onSIGCHLD(self, signum, frame):
+        code = 1
+        while code > 0:
+            code = os.waitpid(-1, os.WNOHANG)
+
+    def start(self,trace=0):
+        if self.cleanup(kill=False):
+            return 1
+
+        # Detach from TTY.
+        if not DEBUG:
+            os.setsid()
+
+        if self.set_user():
+            return 1
+
+        self.install_child_reaper()
+
+        # Fork -- parent writes PID_FILE and exits.
+        pid = os.fork()
+        if pid:
+            # Parent
+            pidfile = open(PID_FILE, 'w')
+            pidfile.write(str(pid))
+            pidfile.close()
+            return 0
+        # Child
+        logfile = self.open_logfile()
+        self.redirect_output(logfile)
+        if trace:
+            self.tracefile = open('/var/log/xend.trace', 'w+', 1)
+            self.traceindent = 0
+            sys.settrace(self.trace)
+            try:
+                threading.settrace(self.trace) # Only in Python >= 2.3
+            except:
+                pass
+        self.run()
+        return 0
+
+    def print_trace(self,str):
+        for i in range(self.traceindent):
+            self.tracefile.write("    ")
+        self.tracefile.write(str)
+            
+    def trace(self, frame, event, arg):
+        if event == 'call':
+            code = frame.f_code
+            filename = code.co_filename
+            m = re.search('.*xenmgr/(.*)', code.co_filename)
+            if not m:
+                return None
+            modulename = m.group(1)
+            if re.search('sxp.py', modulename):
+                return None
+            self.traceindent += 1
+            self.print_trace("++++ %s:%s\n"
+                             % (modulename, code.co_name))
+        elif event == 'line':
+            filename = frame.f_code.co_filename
+            lineno = frame.f_lineno
+            self.print_trace("%4d %s" %
+                             (lineno, linecache.getline(filename, lineno)))
+        elif event == 'return':
+            code = frame.f_code
+            filename = code.co_filename
+            m = re.search('.*xenmgr/(.*)', code.co_filename)
+            if not m:
+                return None
+            modulename = m.group(1)
+            self.print_trace("---- %s:%s\n"
+                             % (modulename, code.co_name))
+            self.traceindent -= 1
+        elif event == 'exception':
+            pass
+        return self.trace
+
+    def open_logfile(self):
+        if not os.path.exists(CONTROL_DIR):
+            os.makedirs(CONTROL_DIR)
+
+        # Open log file. Truncate it if non-empty, and request line buffering.
+        if os.path.isfile(LOG_FILE):
+            os.rename(LOG_FILE, LOG_FILE+'.old')
+        logfile = open(LOG_FILE, 'w+', 1)
+        return logfile
+
+    def set_user(self):
+        # Set the UID.
+        try:
+            os.setuid(pwd.getpwnam(USER)[2])
+            return 0
+        except KeyError, error:
+            print "Error: no such user '%s'" % USER
+            return 1
+
+    def redirect_output(self, logfile):
+        if DEBUG: return
+        # Close down standard file handles
+        try:
+            os.close(0) # stdin
+            os.close(1) # stdout
+            os.close(2) # stderr
+        except:
+            pass
+        # Redirect output to log file.
+        sys.stdout = sys.stderr = logfile
+
+    def stop(self):
+        return self.cleanup(kill=True)
+
+    def run(self):
+        self.createFactories()
+        self.listenMgmt()
+        self.listenEvent()
+        self.listenNotifier()
+        self.listenVirq()
+        SrvServer.create(bridge=1)
+        reactor.run()
+
+    def createFactories(self):
+        self.channelF = channel.channelFactory()
+        self.domainCF = domain.DomainControllerFactory()
+        self.blkifCF = blkif.BlkifControllerFactory()
+        self.netifCF = netif.NetifControllerFactory()
+        self.consoleCF = console.ConsoleControllerFactory()
+
+    def listenMgmt(self):
+        protocol = MgmtProtocol(self)
+        s = os.path.join(CONTROL_DIR, MGMT_SOCK)
+        if os.path.exists(s):
+            os.unlink(s)
+        return reactor.listenUNIXDatagram(s, protocol)
+
+    def listenEvent(self):
+        protocol = EventFactory(self)
+        return reactor.listenTCP(EVENT_PORT, protocol)
+
+    def listenNotifier(self):
+        protocol = NotifierProtocol(self.channelF)
+        p = NotifierPort(self, self.channelF.notifier, protocol, reactor)
+        p.startListening()
+        return p
+
+    def listenVirq(self):
+        virqChan = self.channelF.virqChannel(channel.VIRQ_DOM_EXC)
+        virqChan.registerClient(VirqClient(self))
+
+    def exit(self):
+        reactor.diconnectAll()
+        sys.exit(0)
+
+    def blkif_set_control_domain(self, dom, recreate=0):
+        """Set the block device backend control domain.
+        """
+        return self.blkifCF.setControlDomain(dom, recreate=recreate)
+    
+    def blkif_get_control_domain(self, dom):
+        """Get the block device backend control domain.
+        """
+        return self.blkifCF.getControlDomain()
+    
+    def blkif_create(self, dom, recreate=0):
+        """Create a block device interface controller.
+        
+        Returns Deferred
+        """
+        d = self.blkifCF.createInstance(dom, recreate=recreate)
+        return d
+
+    def blkifs(self):
+        return [ x.sxpr() for x in self.blkifCF.getInstances() ]
+
+    def blkif_get(self, dom):
+        return self.blkifCF.getInstanceByDom(dom)
+
+    def blkif_dev(self, dom, vdev):
+        return self.blkifCF.getDomainDevice(dom, vdev)
+
+    def blkif_dev_create(self, dom, vdev, mode, segment, recreate=0):
+        """Create a block device.
+        
+        Returns Deferred
+        """
+        ctrl = self.blkifCF.getInstanceByDom(dom)
+        if not ctrl:
+            raise ValueError('No blkif controller: %d' % dom)
+        print 'blkif_dev_create>', dom, vdev, mode, segment
+        d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate)
+        return d
+
+    def netif_set_control_domain(self, dom, recreate=0):
+        """Set the network interface backend control domain.
+        """
+        return self.netifCF.setControlDomain(dom, recreate=recreate)
+
+    def netif_get_control_domain(self, dom):
+        """Get the network interface backend control domain.
+        """
+        return self.netifCF.getControlDomain()
+    
+    def netif_create(self, dom, recreate=0):
+        """Create a network interface controller.
+        
+        """
+        return self.netifCF.createInstance(dom, recreate=recreate)
+
+    def netifs(self):
+        return [ x.sxpr() for x in self.netifCF.getInstances() ]
+
+    def netif_get(self, dom):
+        return self.netifCF.getInstanceByDom(dom)
+
+    def netif_dev_create(self, dom, vif, vmac, recreate=0):
+        """Create a network device.
+
+        todo
+        """
+        ctrl = self.netifCF.getInstanceByDom(dom)
+        if not ctrl:
+            raise ValueError('No netif controller: %d' % dom)
+        d = ctrl.attachDevice(vif, vmac, recreate=recreate)
+        return d
+
+    def netif_dev(self, dom, vif):
+        return self.netifCF.getDomainDevice(dom, vif)
+
+    def console_create(self, dom, console_port=None):
+        """Create a console for a domain.
+        """
+        console = self.consoleCF.getInstanceByDom(dom)
+        if console is None:
+            console = self.consoleCF.createInstance(dom, console_port)
+        return console.sxpr()
+
+    def consoles(self):
+        return [ c.sxpr() for c in self.consoleCF.getInstances() ]
+
+    def get_console(self, id):
+        return self.consoleCF.getInstance(id)
+
+    def get_domain_console(self, dom):
+        return self.consoleCF.getInstanceByDom(dom)
+
+    def console_disconnect(self, id):
+        """Disconnect any connected console client.
+        """
+        console = self.get_console(id)
+        if not console:
+            raise ValueError('Invalid console id')
+        console.disconnect()
+
+    def domain_shutdown(self, dom, reason):
+        """Shutdown a domain.
+        """
+        ctrl = self.domainCF.getInstanceByDom(dom)
+        if not ctrl:
+            raise ValueError('No domain controller: %d' % dom)
+        ctrl.shutdown(reason)
+        return 0
+        
+def instance():
+    global inst
+    try:
+        inst
+    except:
+        inst = Daemon()
+    return inst
diff --git a/tools/python/xen/xend/server/SrvDeviceDir.py b/tools/python/xen/xend/server/SrvDeviceDir.py
new file mode 100644 (file)
index 0000000..52f4285
--- /dev/null
@@ -0,0 +1,9 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from SrvDir import SrvDir
+
+class SrvDeviceDir(SrvDir):
+    """Device directory.
+    """
+
+    pass
diff --git a/tools/python/xen/xend/server/SrvDir.py b/tools/python/xen/xend/server/SrvDir.py
new file mode 100644 (file)
index 0000000..c49c0b3
--- /dev/null
@@ -0,0 +1,91 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from twisted.web import error
+from xen.xend import sxp
+from SrvBase import SrvBase
+
+class SrvConstructor:
+    """Delayed constructor for sub-servers.
+    Does not import the sub-server class or create the object until needed.
+    """
+    
+    def __init__(self, klass):
+        """Create a constructor. It is assumed that the class
+        should be imported as 'import klass from klass'.
+
+        klass  name of its class
+        """
+        self.klass = klass
+        self.obj = None
+
+    def getobj(self):
+        """Get the sub-server object, importing its class and instantiating it if
+        necessary.
+        """
+        if not self.obj:
+            exec 'from %s import %s' % (self.klass, self.klass)
+            klassobj = eval(self.klass)
+            self.obj = klassobj()
+        return self.obj
+
+class SrvDir(SrvBase):
+    """Base class for directory servlets.
+    """
+    isLeaf = False
+    
+    def __init__(self):
+        SrvBase.__init__(self)
+        self.table = {}
+        self.order = []
+
+    def getChild(self, x, req):
+        if x == '': return self
+        val = self.get(x)
+        if val is None:
+            return error.NoResource('Not found')
+        else:
+            return val
+
+    def get(self, x):
+        val = self.table.get(x)
+        if val is not None:
+            val = val.getobj()
+        return val
+
+    def add(self, x, xclass = None):
+        if xclass is None:
+            xclass = 'SrvDir'
+        self.table[x] = SrvConstructor(xclass)
+        self.order.append(x)
+
+    def render_GET(self, req):
+        if self.use_sxp(req):
+            req.setHeader("Content-type", sxp.mime_type)
+            self.ls(req, 1)
+        else:
+            req.write('<html><head></head><body>')
+            self.print_path(req)
+            self.ls(req)
+            self.form(req)
+            req.write('</body></html>')
+        return ''
+            
+    def ls(self, req, use_sxp=0):
+        url = req.prePathURL()
+        if not url.endswith('/'):
+            url += '/'
+        if use_sxp:
+           req.write('(ls ')
+           for k in self.order:
+               req.write(' ' + k)
+           req.write(')')
+        else:
+            req.write('<ul>')
+            for k in self.order:
+                v = self.get(k)
+                req.write('<li><a href="%s%s">%s</a></li>'
+                          % (url, k, k))
+            req.write('</ul>')
+
+    def form(self, req):
+        pass
diff --git a/tools/python/xen/xend/server/SrvDomain.py b/tools/python/xen/xend/server/SrvDomain.py
new file mode 100644 (file)
index 0000000..156198b
--- /dev/null
@@ -0,0 +1,195 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from xen.xend import sxp
+from xen.xend import XendDomain
+from xen.xend import XendConsole
+from xen.xend import PrettyPrint
+from xen.xend.Args import FormFn
+
+from SrvDir import SrvDir
+
+class SrvDomain(SrvDir):
+    """Service managing a single domain.
+    """
+
+    def __init__(self, dom):
+        SrvDir.__init__(self)
+        self.dom = dom
+        self.xd = XendDomain.instance()
+        self.xconsole = XendConsole.instance()
+
+    def op_unpause(self, op, req):
+        val = self.xd.domain_unpause(self.dom.id)
+        return val
+        
+    def op_pause(self, op, req):
+        val = self.xd.domain_pause(self.dom.id)
+        return val
+
+    def op_shutdown(self, op, req):
+        val = self.xd.domain_shutdown(self.dom.id)
+        req.setResponseCode(202)
+        req.setHeader("Location", "%s/.." % req.prePathURL())
+        return val
+
+    def op_destroy(self, op, req):
+        val = self.xd.domain_destroy(self.dom.id)
+        req.setHeader("Location", "%s/.." % req.prePathURL())
+        return val
+
+    def op_save(self, op, req):
+        fn = FormFn(self.xd.domain_save,
+                    [['dom', 'int'],
+                     ['file', 'str']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_migrate(self, op, req):
+        fn = FormFn(self.xd.domain_migrate,
+                    [['dom', 'int'],
+                     ['destination', 'str']])
+        val = fn(req.args, {'dom': self.dom.id})
+        val = 0 # Some migrate id.
+        req.setResponseCode(202)
+        #req.send_header("Location", "%s/.." % self.path) # Some migrate url.
+        return val
+
+    def op_pincpu(self, op, req):
+        fn = FormFn(self.xd.domain_pincpu,
+                    [['dom', 'int'],
+                     ['cpu', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_cpu_bvt_set(self, op, req):
+        fn = FormFn(self.xd.domain_cpu_bvt_set,
+                    [['dom', 'int'],
+                     ['mcuadv', 'int'],
+                     ['warp', 'int'],
+                     ['warpl', 'int'],
+                     ['warpu', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_cpu_atropos_set(self, op, req):
+        fn = FormFn(self.xd.domain_cpu_atropos_set,
+                    [['dom', 'int'],
+                     ['period', 'int'],
+                     ['slice', 'int'],
+                     ['latency', 'int'],
+                     ['xtratime', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vifs(self, op, req):
+        return self.xd.domain_vif_ls(self.dom.id)
+
+    def op_vif(self, op, req):
+        fn = FormFn(self.xd.domain_vif_get,
+                    [['dom', 'int'],
+                     ['vif', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vif_stats(self, op, req):
+        #todo
+        fn = FormFn(self.xd.domain_vif_stats,
+                    [['dom', 'int'],
+                     ['vif', 'int']])
+        #val = fn(req.args, {'dom': self.dom.id})
+        val = 999
+        #return val
+        return val
+
+    def op_vif_ip_add(self, op, req):
+        fn = FormFn(self.xd.domain_vif_ip_add,
+                    [['dom', 'int'],
+                     ['vif', 'int'],
+                     ['ip', 'str']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vif_scheduler_set(self, op, req):
+        fn = FormFn(self.xd.domain_vif_scheduler_set,
+                    [['dom', 'int'],
+                     ['vif', 'int'],
+                     ['bytes', 'int'],
+                     ['usecs', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vif_scheduler_get(self, op, req):
+        fn = FormFn(self.xd.domain_vif_scheduler_set,
+                    [['dom', 'int'],
+                     ['vif', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vbds(self, op, req):
+        return self.xd.domain_vbd_ls(self.dom.id)
+
+    def op_vbd(self, op, req):
+        fn = FormFn(self.xd.domain_vbd_get,
+                    [['dom', 'int'],
+                     ['vbd', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vbd_add(self, op, req):
+        fn = FormFn(self.xd.domain_vbd_add,
+                    [['dom', 'int'],
+                     ['uname', 'str'],
+                     ['dev', 'str'],
+                     ['mode', 'str']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_vbd_remove(self, op, req):
+        fn = FormFn(self.xd.domain_vbd_remove,
+                    [['dom', 'int'],
+                     ['dev', 'str']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def render_POST(self, req):
+        return self.perform(req)
+        
+    def render_GET(self, req):
+        op = req.args.get('op')
+        if op and op[0] in ['vifs', 'vif', 'vif_stats', 'vbds', 'vbd']:
+            return self.perform(req)
+        if self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            sxp.show(self.dom.sxpr(), out=req)
+        else:
+            req.write('<html><head></head><body>')
+            self.print_path(req)
+            #self.ls()
+            req.write('<p>%s</p>' % self.dom)
+            if self.dom.console:
+                cinfo = self.dom.console
+                cid = cinfo.id
+                #todo: Local xref: need to know server prefix.
+                req.write('<p><a href="/xend/console/%s">Console %s</a></p>'
+                          % (cid, cid))
+                req.write('<p><a href="%s">Connect to console</a></p>'
+                          % cinfo.uri())
+            if self.dom.config:
+                req.write("<code><pre>")
+                PrettyPrint.prettyprint(self.dom.config, out=req)
+                req.write("</pre></code>")
+            req.write('<a href="%s?op=vif_stats&vif=0">vif 0 stats</a>'
+                      % req.prePathURL())
+            self.form(req)
+            req.write('</body></html>')
+        return ''
+
+    def form(self, req):
+        req.write('<form method="post" action="%s">' % req.prePathURL())
+        req.write('<input type="submit" name="op" value="unpause">')
+        req.write('<input type="submit" name="op" value="pause">')
+        req.write('<input type="submit" name="op" value="shutdown">')
+        req.write('<input type="submit" name="op" value="destroy">')
+        req.write('<br><input type="submit" name="op" value="migrate">')
+        req.write('To: <input type="text" name="destination">')
+        req.write('</form>')
diff --git a/tools/python/xen/xend/server/SrvDomainDir.py b/tools/python/xen/xend/server/SrvDomainDir.py
new file mode 100644 (file)
index 0000000..af4bc7a
--- /dev/null
@@ -0,0 +1,144 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from StringIO import StringIO
+
+from twisted.protocols import http
+from twisted.web import error
+
+from xen.xend import sxp
+from xen.xend import XendDomain
+from xen.xend.Args import FormFn
+
+from SrvDir import SrvDir
+from SrvDomain import SrvDomain
+
+class SrvDomainDir(SrvDir):
+    """Service that manages the domain directory.
+    """
+
+    def __init__(self):
+        SrvDir.__init__(self)
+        self.xd = XendDomain.instance()
+
+    def domain(self, x):
+        val = None
+        try:
+            dom = self.xd.domain_get(x)
+            val = SrvDomain(dom)
+        except KeyError, ex:
+            print 'SrvDomainDir>', ex
+            pass
+        return val
+
+    def get(self, x):
+        v = SrvDir.get(self, x)
+        if v is not None:
+            return v
+        v = self.domain(x)
+        return v
+
+    def op_create(self, op, req):
+        ok = 0
+        try:
+            configstring = req.args.get('config')[0]
+            print 'config:', configstring
+            pin = sxp.Parser()
+            pin.input(configstring)
+            pin.input_eof()
+            config = pin.get_val()
+            ok = 1
+        except Exception, ex:
+            print 'op_create>', ex
+        if not ok:
+            req.setResponseCode(http.BAD_REQUEST, "Invalid configuration")
+            return "Invalid configuration"
+            return error.ErrorPage(http.BAD_REQUEST,
+                                   "Invalid",
+                                   "Invalid configuration")
+        try:
+            deferred = self.xd.domain_create(config)
+            deferred.addCallback(self._cb_op_create, configstring, req)
+            return deferred
+        except Exception, ex:
+            raise
+            #return ['err', str(ex) ]
+            #req.setResponseCode(http.BAD_REQUEST, "Error creating domain")
+            #return str(ex)
+            #return error.ErrorPage(http.BAD_REQUEST,
+            #                       "Error creating domain",
+            #                       str(ex))
+                                   
+
+    def _cb_op_create(self, dominfo, configstring, req):
+        """Callback to handle deferred domain creation.
+        """
+        dom = dominfo.id
+        domurl = "%s/%s" % (req.prePathURL(), dom)
+        req.setResponseCode(201, "created")
+        req.setHeader("Location", domurl)
+        if self.use_sxp(req):
+            return dominfo.sxpr()
+        else:
+            out = StringIO()
+            print >> out, ('<p> Created <a href="%s">Domain %s</a></p>'
+                           % (domurl, dom))
+            print >> out, '<p><pre>'
+            print >> out, configstring
+            print >> out, '</pre></p>'
+            val = out.getvalue()
+            out.close()
+            return val
+
+    def op_restore(self, op, req):
+        fn = FormFn(self.xd.domain_restore,
+                    [['file', 'str']])
+        val = fn(req.args)
+        return val
+        
+    def render_POST(self, req):
+        return self.perform(req)
+
+    def render_GET(self, req):
+        if self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            self.ls_domain(req, 1)
+        else:
+            req.write("<html><head></head><body>")
+            self.print_path(req)
+            self.ls(req)
+            self.ls_domain(req)
+            self.form(req)
+            req.write("</body></html>")
+        return ''
+
+    def ls_domain(self, req, use_sxp=0):
+        url = req.prePathURL()
+        if not url.endswith('/'):
+            url += '/'
+        if use_sxp:
+            domains = self.xd.domain_ls()
+            sxp.show(domains, out=req)
+        else:
+            domains = self.xd.domains()
+            domains.sort(lambda x, y: cmp(x.id, y.id))
+            req.write('<ul>')
+            for d in domains:
+               req.write('<li><a href="%s%s"> Domain %s</a>'
+                         % (url, d.id, d.id))
+               req.write('name=%s' % d.name)
+               req.write('memory=%d'% d.memory)
+               req.write('</li>')
+            req.write('</ul>')
+
+    def form(self, req):
+        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
+                  % req.prePathURL())
+        req.write('<button type="submit" name="op" value="create">Create Domain</button>')
+        req.write('Config <input type="file" name="config"><br>')
+        req.write('</form>')
+        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
+                  % req.prePathURL())
+        req.write('<button type="submit" name="op" value="create">Restore Domain</button>')
+        req.write('State <input type="string" name="state"><br>')
+        req.write('</form>')
+        
diff --git a/tools/python/xen/xend/server/SrvEventDir.py b/tools/python/xen/xend/server/SrvEventDir.py
new file mode 100644 (file)
index 0000000..02871a4
--- /dev/null
@@ -0,0 +1,41 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from xen.xend import sxp
+from xen.xend import EventServer
+from SrvDir import SrvDir
+
+class SrvEventDir(SrvDir):
+    """Event directory.
+    """
+
+    def __init__(self):
+        SrvDir.__init__(self)
+        self.eserver = EventServer.instance()
+
+    def op_inject(self, op, req):
+        eventstring = req.args.get('event')
+        pin = sxp.Parser()
+        pin.input(eventstring)
+        pin.input_eof()
+        sxpr = pin.get_val()
+        self.eserver.inject(sxp.name(sxpr), sxpr)
+        if req.use_sxp:
+            sxp.name(sxpr)
+        else:
+            return '<code>' + eventstring + '</code>'
+        
+    def render_POST(self, req):
+        return self.perform(req)
+
+    def form(self, req):
+        action = req.prePathURL()
+        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
+                  % action)
+        req.write('<button type="submit" name="op" value="inject">Inject</button>')
+        req.write('Event <input type="text" name="event" size="40"><br>')
+        req.write('</form>')
+        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
+                  % action)
+        req.write('<button type="submit" name="op" value="inject">Inject</button>')
+        req.write('Event file<input type="file" name="event"><br>')
+        req.write('</form>')
diff --git a/tools/python/xen/xend/server/SrvNode.py b/tools/python/xen/xend/server/SrvNode.py
new file mode 100644 (file)
index 0000000..69747d8
--- /dev/null
@@ -0,0 +1,54 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+import os
+from SrvDir import SrvDir
+from xen.xend import sxp
+from xen.xend import XendNode
+
+class SrvNode(SrvDir):
+    """Information about the node.
+    """
+
+    def __init__(self):
+        SrvDir.__init__(self)
+        self.xn = XendNode.instance()
+
+    def op_shutdown(self, op, req):
+        val = self.xn.shutdown()
+        return val
+
+    def op_reboot(self, op, req):
+        val = self.xn.reboot()
+        return val
+
+    def op_cpu_rrobin_slice_set(self, op, req):
+        fn = FormFn(self.xn.cpu_rrobin_slice_set,
+                    [['slice', 'int']])
+        val = fn(req.args, {})
+        return val
+
+    def op_cpu_bvt_slice_set(self, op, req):
+        fn = FormFn(self.xn.cpu_bvt_slice_set,
+                    [['slice', 'int']])
+        val = fn(req.args, {})
+        return val
+
+    def render_POST(self, req):
+        return self.perform(req)
+
+    def render_GET(self, req):
+        if self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            sxp.show(['node'] + self.info(), out=req)
+        else:
+            req.write('<html><head></head><body>')
+            self.print_path(req)
+            req.write('<ul>')
+            for d in self.info():
+                req.write('<li> %10s: %s' % (d[0], str(d[1])))
+            req.write('</ul>')
+            req.write('</body></html>')
+        return ''
+            
+    def info(self):
+        return self.xn.info()
diff --git a/tools/python/xen/xend/server/SrvRoot.py b/tools/python/xen/xend/server/SrvRoot.py
new file mode 100644 (file)
index 0000000..8d38937
--- /dev/null
@@ -0,0 +1,30 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from xen.xend import XendRoot
+xroot = XendRoot.instance()
+from SrvDir import SrvDir
+
+class SrvRoot(SrvDir):
+    """The root of the xend server.
+    """
+
+    """Server sub-components. Each entry is (name, class), where
+    'name' is the entry name and  'class' is the name of its class.
+    """
+    #todo Get this list from the XendRoot config.
+    subdirs = [
+        ('node',    'SrvNode'       ),
+        ('domain',  'SrvDomainDir'  ),
+        ('console', 'SrvConsoleDir' ),
+        ('event',   'SrvEventDir'   ),
+        ('device',  'SrvDeviceDir'  ),
+        ('vnet',    'SrvVnetDir'    ),
+        ]
+
+    def __init__(self):
+        SrvDir.__init__(self)
+        for (name, klass) in self.subdirs:
+            self.add(name, klass)
+        for (name, klass) in self.subdirs:
+            self.get(name)
+        xroot.start()
diff --git a/tools/python/xen/xend/server/SrvServer.py b/tools/python/xen/xend/server/SrvServer.py
new file mode 100644 (file)
index 0000000..ac201dd
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/python2
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Example xend HTTP and console server.
+
+   Can be accessed from a browser or from a program.
+   Do 'python SrvServer.py' to run the server.
+   Then point a web browser at http://localhost:8000/xend and follow the links.
+   Most are stubs, except /domain which has a list of domains and a 'create domain'
+   button.
+
+   You can also access the server from a program.
+   Do 'python XendClient.py' to run a few test operations.
+
+   The data served differs depending on the client (as defined by User-Agent
+   and Accept in the HTTP headers). If the client is a browser, data
+   is returned in HTML, with interactive forms. If the client is a program,
+   data is returned in SXP format, with no forms.
+
+   The server serves to the world by default. To restrict it to the local host
+   change 'interface' in main().
+
+   Mike Wray <mike.wray@hp.com>
+"""
+# todo Support security settings etc. in the config file.
+# todo Support command-line args.
+
+from twisted.web import server
+from twisted.web import resource
+from twisted.internet import reactor
+
+from xen.xend import XendRoot
+xroot = XendRoot.instance()
+
+from xen.xend import Vifctl
+
+from SrvRoot import SrvRoot
+
+def create(port=None, interface=None, bridge=0):
+    if port is None: port = 8000
+    if interface is None: interface = ''
+    if bridge or xroot.rebooted:
+        init_bridge()
+    root = resource.Resource()
+    xend = SrvRoot()
+    root.putChild('xend', xend)
+    site = server.Site(root)
+    reactor.listenTCP(port, site, interface=interface)
+
+def init_bridge():
+    Vifctl.init()
+
+def main(port=None, interface=None):
+    create(port, interface)
+    reactor.run()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/python/xen/xend/server/SrvVnetDir.py b/tools/python/xen/xend/server/SrvVnetDir.py
new file mode 100644 (file)
index 0000000..a8a8141
--- /dev/null
@@ -0,0 +1,9 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from SrvDir import SrvDir
+
+class SrvVnetDir(SrvDir):
+    """Vnet directory.
+    """
+
+    pass
diff --git a/tools/python/xen/xend/server/__init__.py b/tools/python/xen/xend/server/__init__.py
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py
new file mode 100755 (executable)
index 0000000..4e2a49f
--- /dev/null
@@ -0,0 +1,341 @@
+from twisted.internet import defer
+
+from xen.xend import sxp
+from xen.xend import PrettyPrint
+
+import channel
+import controller
+from messages import *
+
+class BlkifControllerFactory(controller.ControllerFactory):
+    """Factory for creating block device interface controllers.
+    Also handles the 'back-end' channel to the device driver domain.
+    """
+
+    def __init__(self):
+        controller.ControllerFactory.__init__(self)
+
+        self.majorTypes = [ CMSG_BLKIF_BE ]
+
+        self.subTypes = {
+            CMSG_BLKIF_BE_CREATE     : self.recv_be_create,
+            CMSG_BLKIF_BE_CONNECT    : self.recv_be_connect,
+            CMSG_BLKIF_BE_VBD_CREATE : self.recv_be_vbd_create,
+            CMSG_BLKIF_BE_VBD_GROW   : self.recv_be_vbd_grow,
+            CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
+            }
+        self.attached = 1
+        self.registerChannel()
+
+    def createInstance(self, dom, recreate=0):
+        d = self.addDeferred()
+        blkif = self.getInstanceByDom(dom)
+        if blkif:
+            self.callDeferred(blkif)
+        else:
+            blkif = BlkifController(self, dom)
+            self.addInstance(blkif)
+            if recreate:
+                self.callDeferred(blkif)
+            else:
+                blkif.send_be_create()
+        return d
+
+    def getDomainDevices(self, dom):
+        blkif = self.getInstanceByDom(dom)
+        return (blkif and blkif.getDevices()) or []
+
+    def getDomainDevice(self, dom, vdev):
+        blkif = self.getInstanceByDom(dom)
+        return (blkif and blkif.getDevice(vdev)) or None
+
+    def setControlDomain(self, dom, recreate=0):
+        if self.dom == dom: return
+        self.deregisterChannel()
+        if not recreate:
+            self.attached = 0
+        self.dom = dom
+        self.registerChannel()
+        #
+        #if xend.blkif.be_port:
+        #    xend.blkif.recovery = True
+        #xend.blkif.be_port = xend.main.port_from_dom(dom)
+
+    def getControlDomain(self):
+        return self.dom
+
+    def reattachDevice(self, dom, vdev):
+        blkif = self.getInstanceByDom(dom)
+        if blkif:
+            blkif.reattachDevice(vdev)
+        self.attached = self.devicesAttached()
+        if self.attached:
+            self.reattached()
+
+    def devicesAttached(self):
+        """Check if all devices are attached.
+        """
+        attached = 1
+        for blkif in self.getInstances():
+            if not blkif.attached:
+                attached = 0
+                break
+        return attached
+                         
+    def reattached(self):
+        for blkif in self.getInstances():
+            blkif.reattached()
+
+    def recv_be_create(self, msg, req):
+        #print 'recv_be_create>'
+        val = unpackMsg('blkif_be_create_t', msg)
+        blkif = self.getInstanceByDom(val['domid'])
+        self.callDeferred(blkif)
+    
+    def recv_be_connect(self, msg, req):
+        #print 'recv_be_create>'
+        val = unpackMsg('blkif_be_connect_t', msg)
+        blkif = self.getInstanceByDom(val['domid'])
+        if blkif:
+            blkif.send_fe_interface_status_changed()
+        else:
+            pass
+    
+    def recv_be_vbd_create(self, msg, req):
+        #print 'recv_be_vbd_create>'
+        val = unpackMsg('blkif_be_vbd_create_t', msg)
+        blkif = self.getInstanceByDom(val['domid'])
+        if blkif:
+            blkif.send_be_vbd_grow(val['vdevice'])
+        else:
+            pass
+    
+    def recv_be_vbd_grow(self, msg, req):
+        #print 'recv_be_vbd_grow>'
+        val = unpackMsg('blkif_be_vbd_grow_t', msg)
+        # Check status?
+        if self.attached:
+            self.callDeferred(0)
+        else:
+            self.reattachDevice(val['domid'], val['vdevice'])
+
+    def recv_be_driver_status_changed(self, msg, req):
+        val = unpackMsg('blkif_be_driver_status_changed_t', msg)
+        status = val['status']
+        if status == BLKIF_DRIVER_STATUS_UP and not self.attached:
+            for blkif in self.getInstances():
+                blkif.detach()
+
+class BlkDev(controller.Dev):
+    """Info record for a block device.
+    """
+
+    def __init__(self, ctrl, vdev, mode, segment):
+        controller.Dev.__init__(self, ctrl)
+        self.vdev = vdev
+        self.mode = mode
+        self.device = segment['device']
+        self.start_sector = segment['start_sector']
+        self.nr_sectors = segment['nr_sectors']
+        self.attached = 1
+
+    def readonly(self):
+        return 'w' not in self.mode
+
+    def sxpr(self):
+        val = ['blkdev', ['vdev', self.vdev], ['mode', self.mode] ]
+        return val
+
+    def destroy(self):
+        print 'BlkDev>destroy>', self.vdev
+        PrettyPrint.prettyprint(self.sxpr())
+        self.controller.send_be_vbd_destroy(self.vdev)
+        
+class BlkifController(controller.Controller):
+    """Block device interface controller. Handles all block devices
+    for a domain.
+    """
+    
+    def __init__(self, factory, dom):
+        #print 'BlkifController> dom=', dom
+        controller.Controller.__init__(self, factory, dom)
+        self.devices = {}
+
+        self.majorTypes = [ CMSG_BLKIF_FE ]
+
+        self.subTypes = {
+            CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
+                self.recv_fe_driver_status_changed,
+            CMSG_BLKIF_FE_INTERFACE_CONNECT    :
+                self.recv_fe_interface_connect,
+            }
+        self.attached = 1
+        self.evtchn = None
+        self.registerChannel()
+        #print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx
+
+    def sxpr(self):
+        val = ['blkif', ['dom', self.dom]]
+        if self.evtchn:
+            val.append(['evtchn',
+                        self.evtchn['port1'],
+                        self.evtchn['port2']])
+        return val
+
+    def lostChannel(self):
+        print 'BlkifController>lostChannel>', 'dom=', self.dom
+        #self.destroyDevices()
+        controller.Controller.lostChannel(self)
+
+    def getDevices(self):
+        return self.devices.values()
+
+    def getDevice(self, vdev):
+        return self.devices.get(vdev)
+
+    def addDevice(self, vdev, mode, segment):
+        if vdev in self.devices: return None
+        dev = BlkDev(self, vdev, mode, segment)
+        self.devices[vdev] = dev
+        return dev
+
+    def attachDevice(self, vdev, mode, segment, recreate=0):
+        """Attach a device to the specified interface.
+        """
+        #print 'BlkifController>attach_device>', self.dom, vdev, mode, segment
+        dev = self.addDevice(vdev, mode, segment)
+        if not dev: return -1
+        if recreate:
+            d = defer.Deferred()
+            d.callback(self)
+        else:
+            self.send_be_vbd_create(vdev)
+            d = self.factory.addDeferred()
+        return d
+
+    def destroy(self):
+        print 'BlkifController>destroy> dom=', self.dom
+        def cb_destroy(val):
+            self.send_be_destroy()
+        d = self.factory.addDeferred()
+        d.addCallback(cb_destroy)
+        self.send_be_disconnect()
+        #self.destroyDevices()
+
+    def destroyDevices(self):
+        for dev in self.getDevices():
+            dev.destroy()
+
+    def detach(self):
+        """Detach all devices, when the back-end control domain has changed.
+        """
+        self.attached = 0
+        for dev in self.devices.values():
+            dev.attached = 0
+            self.send_be_vbd_create(vdev)
+
+    def reattachDevice(self, vdev):
+        """Reattach a device, when the back-end control domain has changed.
+        """
+        dev = self.devices[vdev]
+        dev.attached = 1
+        attached = 1
+        for dev in self.devices.values():
+            if not dev.attached:
+                attached = 0
+                break
+        self.attached = attached
+        return self.attached
+
+    def reattached(self):
+        """All devices have been reattached after the back-end control
+        domain has changed.
+        """
+        msg = packMsg('blkif_fe_interface_status_changed_t',
+                      { 'handle' : 0,
+                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED})
+        self.writeRequest(msg)
+
+    def recv_fe_driver_status_changed(self, msg, req):
+        msg = packMsg('blkif_fe_interface_status_changed_t',
+                      { 'handle' : 0,
+                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED,
+                        'evtchn' : 0 })
+        self.writeRequest(msg)
+    
+    def recv_fe_interface_connect(self, msg, req):
+        val = unpackMsg('blkif_fe_interface_connect_t', msg)
+        self.evtchn = channel.eventChannel(0, self.dom)
+        print 'recv_fe_interface_connect>'
+        PrettyPrint.prettyprint(self.sxpr())
+        msg = packMsg('blkif_be_connect_t',
+                      { 'domid'        : self.dom,
+                        'blkif_handle' : val['handle'],
+                        'evtchn'       : self.evtchn['port1'],
+                        'shmem_frame'  : val['shmem_frame'] })
+        self.factory.writeRequest(msg)
+        pass
+
+    #def recv_fe_interface_status_changed(self, msg, req):
+    #    (hnd, status, chan) = unpackMsg('blkif_fe_interface_status_changed_t', msg)
+    #    print 'recv_fe_interface_status_changed>', hnd, status, chan
+    #   pass
+
+    def send_fe_interface_status_changed(self):
+        msg = packMsg('blkif_fe_interface_status_changed_t',
+                      { 'handle' : 0,
+                        'status' : BLKIF_INTERFACE_STATUS_CONNECTED,
+                        'evtchn' : self.evtchn['port2'] })
+        self.writeRequest(msg)
+
+    def send_be_create(self):
+        msg = packMsg('blkif_be_create_t',
+                      { 'domid'        : self.dom,
+                        'blkif_handle' : 0 })
+        self.factory.writeRequest(msg)
+
+    def send_be_disconnect(self):
+        print '>BlkifController>send_be_disconnect>', 'dom=', self.dom
+        msg = packMsg('blkif_be_disconnect_t',
+                      { 'domid'        : self.dom,
+                        'blkif_handle' : 0 })
+        self.factory.writeRequest(msg)
+
+    def send_be_destroy(self):
+        print '>BlkifController>send_be_destroy>', 'dom=', self.dom
+        msg = packMsg('blkif_be_destroy_t',
+                      { 'domid'        : self.dom,
+                        'blkif_handle' : 0 })
+        self.factory.writeRequest(msg)
+
+    def send_be_vbd_create(self, vdev):
+        dev = self.devices[vdev]
+        msg = packMsg('blkif_be_vbd_create_t',
+                      { 'domid'        : self.dom,
+                        'blkif_handle' : 0,
+                        'vdevice'      : dev.vdev,
+                        'readonly'     : dev.readonly() })
+        self.factory.writeRequest(msg)
+        
+    def send_be_vbd_grow(self, vdev):
+        dev = self.devices[vdev]
+        msg = packMsg('blkif_be_vbd_grow_t',
+                      { 'domid'                : self.dom,
+                        'blkif_handle'         : 0,
+                        'vdevice'              : dev.vdev,
+                        'extent.device'        : dev.device,
+                        'extent.sector_start'  : dev.start_sector,
+                        'extent.sector_length' : dev.nr_sectors })
+        self.factory.writeRequest(msg)
+
+    def send_be_vbd_destroy(self, vdev):
+        print '>BlkifController>send_be_vbd_destroy>', 'dom=', self.dom, 'vdev=', vdev
+        PrettyPrint.prettyprint(self.sxpr())
+        dev = self.devices[vdev]
+        msg = packMsg('blkif_be_vbd_destroy_t',
+                      { 'domid'                : self.dom,
+                        'blkif_handle'         : 0,
+                        'vdevice'              : dev.vdev })
+        del self.devices[vdev]
+        self.factory.writeRequest(msg)
+    
diff --git a/tools/python/xen/xend/server/channel.py b/tools/python/xen/xend/server/channel.py
new file mode 100755 (executable)
index 0000000..be98a37
--- /dev/null
@@ -0,0 +1,378 @@
+import xen.ext.xc; xc = xen.ext.xc.new()
+from xen.ext import xu
+from messages import msgTypeName
+
+VIRQ_MISDIRECT  = 0  # Catch-all interrupt for unbound VIRQs.
+VIRQ_TIMER      = 1  # Timebase update, and/or requested timeout.
+VIRQ_DEBUG      = 2  # Request guest to dump debug info.
+VIRQ_CONSOLE    = 3  # (DOM0) bytes received on emergency console.
+VIRQ_DOM_EXC    = 4  # (DOM0) Exceptional event for some domain.
+
+def eventChannel(dom1, dom2):
+    return xc.evtchn_bind_interdomain(dom1=dom1, dom2=dom2)
+
+class ChannelFactory:
+    """Factory for creating channels.
+    Maintains a table of channels.
+    """
+
+    """ Channels indexed by index. """
+    channels = {}
+
+    def __init__(self):
+        """Constructor - do not use. Use the channelFactory function."""
+        self.notifier = xu.notifier()
+    
+    def addChannel(self, channel):
+        """Add a channel.
+        """
+        idx = channel.idx
+        self.channels[idx] = channel
+        self.notifier.bind(idx)
+        # Try to wake it up
+        #self.notifier.unmask(idx)
+        #channel.notify()
+
+    def getChannel(self, idx):
+        """Get the channel with the given index (if any).
+        """
+        return self.channels.get(idx)
+
+    def delChannel(self, idx):
+        """Remove the channel with the given index (if any).
+        """
+        if idx in self.channels:
+            del self.channels[idx]
+            self.notifier.unbind(idx)
+
+    def domChannel(self, dom):
+        """Get the channel for the given domain.
+        Construct if necessary.
+        """
+        dom = int(dom)
+        for chan in self.channels.values():
+            if not isinstance(chan, Channel): continue
+            if chan.dom == dom:
+                return chan
+        chan = Channel(self, dom)
+        self.addChannel(chan)
+        return chan
+
+    def virqChannel(self, virq):
+        """Get the channel for the given virq.
+        Construct if necessary.
+        """
+        for chan in self.channels.values():
+            if not isinstance(chan, VirqChannel): continue
+            if chan.virq == virq:
+                return chan
+        chan = VirqChannel(self, virq)
+        self.addChannel(chan)
+        return chan
+
+    def channelClosed(self, channel):
+        """The given channel has been closed - remove it.
+        """
+        self.delChannel(channel.idx)
+
+    def createPort(self, dom):
+        """Create a port for a channel to the given domain.
+        """
+        return xu.port(dom)
+
+def channelFactory():
+    """Singleton constructor for the channel factory.
+    Use this instead of the class constructor.
+    """
+    global inst
+    try:
+        inst
+    except:
+        inst = ChannelFactory()
+    return inst
+
+class BaseChannel:
+    """Abstract superclass for channels.
+
+    The subclass constructor must set idx to the port to use.
+    """
+
+    def __init__(self, factory):
+        self.factory = factory
+        self.idx = -1
+        self.closed = 0
+
+    def getIndex(self):
+        """Get the channel index.
+        """
+        return self.idx
+
+    def notificationReceived(self, type):
+        """Called when a notification is received.
+        Closes the channel on error, otherwise calls
+        handleNotification(type), which should be defined
+        in a subclass.
+        """
+        #print 'notificationReceived> type=', type, self
+        if self.closed: return
+        if type == self.factory.notifier.EXCEPTION:
+            print 'notificationReceived> EXCEPTION'
+            info = xc.evtchn_status(self.idx)
+            if info['status'] == 'unbound':
+                print 'notificationReceived> EXCEPTION closing...'
+                self.close()
+                return
+        self.handleNotification(type)
+
+    def close(self):
+        """Close the channel. Calls channelClosed() on the factory.
+        Override in subclass.
+        """
+        self.factory.channelClosed(self)
+
+    def handleNotification(self, type):
+        """Handle notification.
+        Define in subclass.
+        """
+        pass
+        
+
+class VirqChannel(BaseChannel):
+    """A channel for handling a virq.
+    """
+    
+    def __init__(self, factory, virq):
+        """Create a channel for the given virq using the given factory.
+
+        Do not call directly, use virqChannel on the factory.
+        """
+        BaseChannel.__init__(self, factory)
+        self.virq = virq
+        # Notification port (int).
+        self.port = xc.evtchn_bind_virq(virq)
+        self.idx = self.port
+        # Clients to call when a virq arrives.
+        self.clients = []
+
+    def __repr__(self):
+        return ('<VirqChannel virq=%d port=%d>'
+                % (self.virq, self.port))
+
+    def getVirq(self):
+        """Get the channel's virq.
+        """
+        return self.virq
+
+    def close(self):
+        """Close the channel. Calls lostChannel(self) on all its clients and
+        channelClosed() on the factory.
+        """
+        for c in self.clients:
+            c.lostChannel(self)
+        del self.clients
+        BaseChannel.close(self)
+
+    def registerClient(self, client):
+        """Register a client. The client will be called with
+        client.virqReceived(virq) when a virq is received.
+        The client will be called with client.lostChannel(self) if the
+        channel is closed.
+        """
+        self.clients.append(client)
+
+    def handleNotification(self, type):
+        for c in self.clients:
+            c.virqReceived(self.virq)
+
+    def notify(self):
+        xc.evtchn_send(self.port)
+
+
+class Channel(BaseChannel):
+    """A control channel to a domain. Messages for the domain device controllers
+    are multiplexed over the channel (console, block devs, net devs).
+    """
+
+    def __init__(self, factory, dom):
+        """Create a channel to the given domain using the given factory.
+
+        Do not call directly, use domChannel on the factory.
+        """
+        BaseChannel.__init__(self, factory)
+        # Domain.
+        self.dom = int(dom)
+        # Domain port (object).
+        self.port = self.factory.createPort(dom)
+        # Channel port (int).
+        self.idx = self.port.local_port
+        # Registered devices.
+        self.devs = []
+        # Devices indexed by the message types they handle.
+        self.devs_by_type = {}
+        # Output queue.
+        self.queue = []
+        self.closed = 0
+
+    def getLocalPort(self):
+        """Get the local port.
+        """
+        return self.port.local_port
+
+    def getRemotePort(self):
+        """Get the remote port.
+        """
+        return self.port.remote_port
+
+    def close(self):
+        """Close the channel. Calls lostChannel() on all its devices and
+        channelClosed() on the factory.
+        """
+        self.closed = 1
+        for d in self.devs:
+            d.lostChannel()
+        self.factory.channelClosed(self)
+        self.devs = []
+        self.devs_by_type = {}
+
+    def registerDevice(self, types, dev):
+        """Register a device controller.
+
+        @param types message types the controller handles
+        @param dev   device controller
+        """
+        if self.closed: return
+        self.devs.append(dev)
+        for ty in types:
+            self.devs_by_type[ty] = dev
+
+    def deregisterDevice(self, dev):
+        """Remove the registration for a device controller.
+
+        @param dev device controller
+        """
+        if dev in self.devs:
+            self.devs.remove(dev)
+        types = [ ty for (ty, d) in self.devs_by_type.items() if d == dev ]
+        for ty in types:
+            del self.devs_by_type[ty]
+
+    def getDevice(self, type):
+        """Get the device controller handling a message type.
+
+        @param type message type
+        @returns controller or None
+        """
+        return self.devs_by_type.get(type)
+
+    def getMessageType(self, msg):
+        """Get a 2-tuple of the message type and subtype.
+        """
+        hdr = msg.get_header()
+        return (hdr['type'], hdr.get('subtype'))
+
+    def __repr__(self):
+        return ('<Channel dom=%d ports=%d:%d>'
+                % (self.dom,
+                   self.port.local_port,
+                   self.port.remote_port))
+
+    def handleNotification(self, type):
+        work = 0
+        work += self.handleRequests()
+        work += self.handleResponses()
+        work += self.handleWrites()
+        if work:
+            self.notify()
+
+    def notify(self):
+        self.port.notify()
+
+    def handleRequests(self):
+        work = 0
+        while 1:
+            msg = self.readRequest()
+            if not msg: break
+            self.requestReceived(msg)
+            work += 1
+        return work
+
+    def requestReceived(self, msg):
+        (ty, subty) = self.getMessageType(msg)
+        #todo:  Must respond before writing any more messages.
+        #todo:  Should automate this (respond on write)
+        self.port.write_response(msg)
+        dev = self.getDevice(ty)
+        if dev:
+            dev.requestReceived(msg, ty, subty)
+        else:
+            print ("requestReceived> No device: Message type %s %d:%d"
+                   % (msgTypeName(ty, subty), ty, subty)), self
+
+    def handleResponses(self):
+        work = 0
+        while 1:
+            msg = self.readResponse()
+            if not msg: break
+            self.responseReceived(msg)
+            work += 1
+        return work
+
+    def responseReceived(self, msg):
+        (ty, subty) = self.getMessageType(msg)
+        dev = self.getDevice(ty)
+        if dev:
+            dev.responseReceived(msg, ty, subty)
+        else:
+            print ("responseReceived> No device: Message type %d:%d"
+                   % (msgTypeName(ty, subty), ty, subty)), self
+
+    def handleWrites(self):
+        work = 0
+        # Pull data from producers.
+        for dev in self.devs:
+            work += dev.produceRequests()
+        # Flush the queue.
+        while self.queue and self.port.space_to_write_request():
+            msg = self.queue.pop(0)
+            self.port.write_request(msg)
+            work += 1
+        return work
+
+    def writeRequest(self, msg, notify=1):
+        if self.closed:
+            val = -1
+        elif self.writeReady():
+            self.port.write_request(msg)
+            if notify: self.notify()
+            val = 1
+        else:
+            self.queue.append(msg)
+            val = 0
+        return val
+
+    def writeResponse(self, msg):
+        if self.closed: return -1
+        self.port.write_response(msg)
+        return 1
+
+    def writeReady(self):
+        if self.closed or self.queue: return 0
+        return self.port.space_to_write_request()
+
+    def readRequest(self):
+        if self.closed:
+            return None
+        if self.port.request_to_read():
+            val = self.port.read_request()
+        else:
+            val = None
+        return val
+        
+    def readResponse(self):
+        if self.closed:
+            return None
+        if self.port.response_to_read():
+            val = self.port.read_response()
+        else:
+            val = None
+        return val
diff --git a/tools/python/xen/xend/server/console.py b/tools/python/xen/xend/server/console.py
new file mode 100755 (executable)
index 0000000..ab8b22e
--- /dev/null
@@ -0,0 +1,232 @@
+
+from twisted.internet import reactor
+from twisted.internet import protocol
+from twisted.protocols import telnet
+
+from xen.ext import xu
+
+from xen.xend import EventServer
+eserver = EventServer.instance()
+
+import controller
+from messages import *
+from params import *
+
+"""Telnet binary option."""
+TRANSMIT_BINARY = '0'
+WILL = chr(251)
+IAC = chr(255)
+
+class ConsoleProtocol(protocol.Protocol):
+    """Asynchronous handler for a console TCP socket.
+    """
+
+    def __init__(self, controller, idx):
+        self.controller = controller
+        self.idx = idx
+        self.addr = None
+        self.binary = 0
+
+    def connectionMade(self):
+        peer = self.transport.getPeer()
+        self.addr = (peer.host, peer.port)
+        if self.controller.connect(self.addr, self):
+            self.transport.write("Cannot connect to console %d on domain %d\n"
+                                 % (self.idx, self.controller.dom))
+            self.loseConnection()
+            return
+        else:
+            # KAF: A nice quiet successful connect. Don't bother with telnet
+            # control sequence -- telnet is not the appropriate protocol here. 
+            #self.transport.write("Connected to console %d on domain %d\n"
+            #                     % (self.idx, self.controller.dom))
+            #self.setTelnetTransmitBinary()
+            eserver.inject('xend.console.connect',
+                           [self.idx, self.addr[0], self.addr[1]])
+
+    def setTelnetTransmitBinary(self):
+        """Send the sequence to set the telnet TRANSMIT-BINARY option.
+        """
+        self.write(IAC + WILL + TRANSMIT_BINARY)
+
+    def dataReceived(self, data):
+        if self.controller.handleInput(self, data):
+            self.loseConnection()
+
+    def write(self, data):
+        #if not self.connected: return -1
+        self.transport.write(data)
+        return len(data)
+
+    def connectionLost(self, reason=None):
+        eserver.inject('xend.console.disconnect',
+                       [self.idx, self.addr[0], self.addr[1]])
+        self.controller.disconnect()
+
+    def loseConnection(self):
+        self.transport.loseConnection()
+
+class ConsoleFactory(protocol.ServerFactory):
+    """Asynchronous handler for a console server socket.
+    """
+    protocol = ConsoleProtocol
+    
+    def __init__(self, controller, idx):
+        #protocol.ServerFactory.__init__(self)
+        self.controller = controller
+        self.idx = idx
+
+    def buildProtocol(self, addr):
+        proto = self.protocol(self.controller, self.idx)
+        proto.factory = self
+        return proto
+
+class ConsoleControllerFactory(controller.ControllerFactory):
+    """Factory for creating console controllers.
+    """
+
+    def createInstance(self, dom, console_port=None):
+        if console_port is None:
+            console_port = CONSOLE_PORT_BASE + dom
+        console = ConsoleController(self, dom, console_port)
+        self.addInstance(console)
+        eserver.inject('xend.console.create',
+                       [console.idx, console.dom, console.console_port])
+        return console
+        
+    def consoleClosed(self, console):
+        eserver.inject('xend.console.close', console.idx)
+        self.delInstance(console)
+
+class ConsoleController(controller.Controller):
+    """Console controller for a domain.
+    Does not poll for i/o itself, but relies on the notifier to post console
+    output and the connected TCP sockets to post console input.
+    """
+
+    def __init__(self, factory, dom, console_port):
+        #print 'ConsoleController> dom=', dom, type(dom)
+        controller.Controller.__init__(self, factory, dom)
+        self.majorTypes = [ CMSG_CONSOLE ]
+        self.status = "new"
+        self.addr = None
+        self.conn = None
+        self.rbuf = xu.buffer()
+        self.wbuf = xu.buffer()
+        self.console_port = console_port
+
+        self.registerChannel()
+        self.listener = None
+        self.listen()
+        #print 'ConsoleController<', 'dom=', self.dom, 'idx=', self.idx
+
+    def sxpr(self):
+        val =['console',
+              ['status',       self.status ],
+              ['id',           self.idx ],
+              ['domain',       self.dom ],
+              ['local_port',   self.channel.getLocalPort() ],
+              ['remote_port',  self.channel.getRemotePort() ],
+              ['console_port', self.console_port ] ]
+        if self.addr:
+            val.append(['connected', self.addr[0], self.addr[1]])
+        return val
+
+    def ready(self):
+        return not (self.closed() or self.rbuf.empty())
+
+    def closed(self):
+        return self.status == 'closed'
+
+    def connected(self):
+        return self.status == 'connected'
+
+    def close(self):
+        try:
+            #print 'ConsoleController> close dom=', self.dom
+            self.status = "closed"
+            if self.conn:
+                self.conn.loseConnection()
+            self.listener.stopListening()
+            self.deregisterChannel()
+            self.lostChannel()
+        except Exception, ex:
+            print 'ConsoleController>close>', ex
+            raise
+
+    def listen(self):
+        """Listen for TCP connections to the console port..
+        """
+        if self.closed(): return
+        self.status = "listening"
+        if self.listener:
+            #self.listener.startListening()
+            pass
+        else:
+            f = ConsoleFactory(self, self.idx)
+            self.listener = reactor.listenTCP(self.console_port, f)
+
+    def connect(self, addr, conn):
+        if self.closed(): return -1
+        if self.connected(): return -1
+        self.addr = addr
+        self.conn = conn
+        self.status = "connected"
+        self.handleOutput()
+        return 0
+
+    def disconnect(self):
+        if self.conn:
+            self.conn.loseConnection()
+        self.addr = None
+        self.conn = None
+        self.listen()
+
+    def requestReceived(self, msg, type, subtype):
+        #print '***Console', self.dom, msg.get_payload()
+        self.rbuf.write(msg.get_payload())
+        self.handleOutput()
+        
+    def responseReceived(self, msg, type, subtype):
+        pass
+
+    def produceRequests(self):
+        # Send as much pending console data as there is room for.
+        work = 0
+        while not self.wbuf.empty() and self.channel.writeReady():
+            msg = xu.message(CMSG_CONSOLE, 0, 0)
+            msg.append_payload(self.wbuf.read(msg.MAX_PAYLOAD))
+            work += self.channel.writeRequest(msg, notify=0)
+        return work
+
+    def handleInput(self, conn, data):
+        """Handle some external input aimed at the console.
+        Called from a TCP connection (conn).
+        """
+        if self.closed(): return -1
+        if conn != self.conn: return 0
+        self.wbuf.write(data)
+        if self.produceRequests():
+            self.channel.notify()
+        return 0
+
+    def handleOutput(self):
+        """Handle buffered output from the console.
+        Sends it to the connected console (if any).
+        """
+        if self.closed():
+            #print 'Console>handleOutput> closed'
+            return -1
+        if not self.conn:
+            #print 'Console>handleOutput> not connected'
+            return 0
+        while not self.rbuf.empty():
+            try:
+                #print 'Console>handleOutput> writing...'
+                bytes = self.conn.write(self.rbuf.peek())
+                if bytes > 0:
+                    self.rbuf.discard(bytes)
+            except socket.error, error:
+                pass
+        #print 'Console>handleOutput<'
+        return 0
diff --git a/tools/python/xen/xend/server/controller.py b/tools/python/xen/xend/server/controller.py
new file mode 100755 (executable)
index 0000000..900c2d5
--- /dev/null
@@ -0,0 +1,169 @@
+from twisted.internet import defer
+
+import channel
+from messages import msgTypeName
+
+class CtrlMsgRcvr:
+    """Abstract class for things that deal with a control interface to a domain.
+    """
+
+
+    def __init__(self):
+        self.channelFactory = channel.channelFactory()
+        self.majorTypes = [ ]
+        self.subTypes = {}
+        self.dom = None
+        self.channel = None
+        self.idx = None
+
+    def requestReceived(self, msg, type, subtype):
+        method = self.subTypes.get(subtype)
+        if method:
+            method(msg, 1)
+        else:
+            print ('requestReceived> No handler: Message type %s %d:%d'
+                   % (msgTypeName(type, subtype), type, subtype)), self
+        
+    def responseReceived(self, msg, type, subtype):
+        method = self.subTypes.get(subtype)
+        if method:
+            method(msg, 0)
+        else:
+            print ('responseReceived> No handler: Message type %s %d:%d'
+                   % (msgTypeName(type, subtype), type, subtype)), self
+
+    def lostChannel(self):
+        pass
+    
+    def registerChannel(self):
+        #print 'CtrlMsgRcvr>registerChannel>', self
+        self.channel = self.channelFactory.domChannel(self.dom)
+        self.idx = self.channel.getIndex()
+        if self.majorTypes:
+            self.channel.registerDevice(self.majorTypes, self)
+        
+    def deregisterChannel(self):
+        #print 'CtrlMsgRcvr>deregisterChannel>', self
+        if self.channel:
+            self.channel.deregisterDevice(self)
+            del self.channel
+
+    def produceRequests(self):
+        return 0
+
+    def writeRequest(self, msg):
+        if self.channel:
+            self.channel.writeRequest(msg)
+        else:
+            print 'CtrlMsgRcvr>writeRequest>', 'no channel!', self
+
+    def writeResponse(self, msg):
+        if self.channel:
+            self.channel.writeResponse(msg)
+        else:
+            print 'CtrlMsgRcvr>writeResponse>', 'no channel!', self
+            
+class ControllerFactory(CtrlMsgRcvr):
+    """Abstract class for factories creating controllers.
+    Maintains a table of instances.
+    """
+
+    def __init__(self):
+        CtrlMsgRcvr.__init__(self)
+        self.instances = {}
+        self.dlist = []
+        self.dom = 0
+        # Timeout (in seconds) for deferreds.
+        self.timeout = 10
+        
+    def addInstance(self, instance):
+        self.instances[instance.idx] = instance
+
+    def getInstance(self, idx):
+        return self.instances.get(idx)
+
+    def getInstances(self):
+        return self.instances.values()
+
+    def getInstanceByDom(self, dom):
+        for inst in self.instances.values():
+            if inst.dom == dom:
+                return inst
+        return None
+
+    def delInstance(self, instance):
+        #print 'ControllerFactory>delInstance>', instance.idx
+        if instance.idx in self.instances:
+            #print 'ControllerFactory>delInstance> remove', instance.idx
+            del self.instances[instance.idx]
+
+    def createInstance(self, dom, recreate=0):
+        raise NotImplementedError()
+
+    def instanceClosed(self, instance):
+        #print 'ControllerFactory>instanceClosed>', instance.idx, instance
+        self.delInstance(instance)
+
+    def addDeferred(self):
+        d = defer.Deferred()
+        if self.timeout > 0:
+            # The deferred will error if not called before timeout.
+            d.setTimeout(self.timeout)
+        self.dlist.append(d)
+        return d
+
+    def callDeferred(self, *args):
+        if self.dlist:
+            d = self.dlist.pop(0)
+            d.callback(*args)
+
+    def errDeferred(self, *args):
+        if self.dlist:
+            d = self.dlist.pop(0)
+            d.errback(*args)
+
+class Controller(CtrlMsgRcvr):
+    """Abstract class for a device controller attached to a domain.
+    """
+
+    def __init__(self, factory, dom):
+        CtrlMsgRcvr.__init__(self)
+        self.factory = factory
+        self.dom = int(dom)
+        self.channel = None
+        self.idx = None
+
+    def close(self):
+        self.deregisterChannel()
+        self.lostChannel()
+
+    def lostChannel(self):
+        #print 'Controller>lostChannel>', self, self.factory
+        self.factory.instanceClosed(self)
+
+class Dev:
+
+    def __init__(self, controller):
+        self.controller = controller
+        self.props = {}
+
+    def setprop(self, k, v):
+        self.props[k] = v
+
+    def getprop(self, k, v=None):
+        return self.props.get(k, v)
+
+    def hasprop(self, k):
+        return k in self.props
+
+    def delprop(self, k):
+        if k in self.props:
+            del self.props[k]
+
+    #def __repr__(self):
+    #    return str(self.sxpr())
+
+    def sxpr(self):
+        raise NotImplementedError()
+
+    
diff --git a/tools/python/xen/xend/server/cstruct.py b/tools/python/xen/xend/server/cstruct.py
new file mode 100755 (executable)
index 0000000..880931b
--- /dev/null
@@ -0,0 +1,269 @@
+import struct
+
+class Struct:
+
+    maxDepth = 10
+
+    base = ['x', 'B', 'H', 'I', 'L', 'Q', 'c', 'h', 'i', 'l', 'q', ]
+
+    sizes = {'B': 1,
+            'H': 2,
+            'I': 4,
+            'L': 4,
+            'Q': 8,
+            'c': 1,
+            'h': 2,
+            'i': 4,
+            'l': 4,
+            'q': 8,
+            'x': 1,
+            }
+
+    formats = {
+        'int8'          : 'B',
+        'int16'         : 'H',
+        'int32'         : 'I',
+        'int64'         : 'Q',
+        'u8'            : 'B',
+        'u16'           : 'H',
+        'u32'           : 'I',
+        'u64'           : 'Q'
+        }
+
+    def typedef(self, name, val):
+        self.formats[name] = val
+
+    def struct(self, name, *f):
+        self.typedef(name, StructInfo(self, f))
+        
+    def getType(self, name):
+        return self.formats[name]
+
+    def format(self, ty):
+        d = 0
+        f = ty
+        while d < self.maxDepth:
+            d += 1
+            f = self.formats[f]
+            if isinstance(f, StructInfo):
+                return f.format()
+            if f in self.base:
+                return f
+        return -1
+
+    def alignedformat(self, ty):
+        fmt = self.format(ty)
+        #print 'alignedformat> %s |%s|' %(ty, fmt)
+        afmt = self.align(fmt)
+        #print 'alignedformat< %s |%s| |%s|' % (ty, fmt, afmt)
+        return afmt
+
+    def align(self, fmt):
+        n1 = 0
+        afmt = ''
+        for a in fmt:
+            n2 = self.getSize(a)
+            m = n1 % n2
+            if m:
+                d = (n2 - m)
+                afmt += 'x' * d
+                n1 += d
+            afmt += a
+            n1 += n2
+        return afmt
+
+    def fmtsize(self, fmt):
+        s = 0
+        for f in fmt:
+            s += self.getSize(f)
+        return s
+
+    def getSize(self, f):
+        return self.sizes[f]
+
+    def pack(self, ty, data):
+        return self.getType(ty).pack(data)
+
+    def unpack(self, ty, data):
+        return self.getType(ty).unpack(data)
+
+    def show(self):
+        l = self.formats.keys()
+        l.sort()
+        for v in l:
+            print "%-35s %-10s %s" % (v, self.format(v), self.alignedformat(v))
+
+
+class StructInfo:
+
+    def __init__(self, s, f):
+        self.fmt = None
+        self.structs = s
+        self.fields = f
+
+    def alignedformat(self):
+        if self.afmt: return self.afmt
+        self.afmt = self.structs.align(self.format())
+        return self.afmt
+    
+    def format(self):
+        if self.fmt: return self.fmt
+        fmt = ""
+        for (ty, name) in self.fields:
+            fmt += self.formatString(ty)
+        self.fmt = fmt
+        return fmt
+
+    def formatString(self, ty):
+        if ty in self.fields:
+            ty = self.fields[ty]
+        return self.structs.format(ty)
+
+    def pack(self, *args):
+        return struct.pack(self.alignedformat(), *args)
+
+    def unpack(self, data):
+        return struct.unpack(self.alignedformat(), data)
+
+types = Struct()
+
+types.typedef('short'         , 'h')
+types.typedef('int'           , 'i')
+types.typedef('long'          , 'l')
+types.typedef('unsigned short', 'H')
+types.typedef('unsigned int'  , 'I')
+types.typedef('unsigned long' , 'L')
+types.typedef('domid_t'       , 'u64')
+types.typedef('blkif_vdev_t'  , 'u16')
+types.typedef('blkif_pdev_t'  , 'u16')
+types.typedef('blkif_sector_t', 'u64')
+
+types.struct('u8[6]',
+             ('u8', 'a1'),
+             ('u8', 'a2'),
+             ('u8', 'a3'),
+             ('u8', 'a4'),
+             ('u8', 'a5'),
+             ('u8', 'a6'))
+             
+types.struct('blkif_fe_interface_status_changed_t',
+    ('unsigned int',    'handle'),
+    ('unsigned int',    'status'),
+    ('unsigned int',    'evtchn'))
+
+types.struct('blkif_fe_driver_status_changed_t',
+    ('unsigned int',    'status'),
+    ('unsigned int',    'nr_interfaces'))
+
+types.struct('blkif_fe_interface_connect_t',
+    ('unsigned int' ,   'handle'),
+    ('unsigned long',   'shmem_frame'))
+
+types.struct('blkif_fe_interface_disconnect_t',
+    ('unsigned int',   'handle'))
+
+types.struct('blkif_extent_t',
+    ('blkif_pdev_t'  , 'device'),
+    ('blkif_sector_t', 'sector_start'),
+    ('blkif_sector_t', 'sector_length'))
+
+types.struct('blkif_be_create_t', 
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'blkif_handle'),
+    ('unsigned int',   'status'))
+             
+types.struct('blkif_be_destroy_t',
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'blkif_handle'),
+    ('unsigned int',   'status'))
+
+types.struct('blkif_be_connect_t',
+    ('domid_t'      ,  'domid'),
+    ('unsigned int' ,  'blkif_handle'),
+    ('unsigned int' ,  'evtchn'),
+    ('unsigned long',  'shmem_frame'),
+    ('unsigned int' ,  'status'))
+
+types.struct('blkif_be_disconnect_t',
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'blkif_handle'),
+    ('unsigned int',   'status'))
+
+types.struct('blkif_be_vbd_create_t', 
+    ('domid_t'     ,   'domid'),         #Q
+    ('unsigned int',   'blkif_handle'),  #I
+    ('blkif_vdev_t',   'vdevice'),       #H
+    ('int'         ,   'readonly'),      #i
+    ('unsigned int',   'status'))        #I
+
+types.struct('blkif_be_vbd_destroy_t', 
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'blkif_handle'),
+    ('blkif_vdev_t',   'vdevice'),
+    ('unsigned int',   'status'))
+
+types.struct('blkif_be_vbd_grow_t', 
+    ('domid_t'       , 'domid'),         #Q
+    ('unsigned int'  , 'blkif_handle'),  #I
+    ('blkif_vdev_t'  , 'vdevice'),       #H   
+    ('blkif_extent_t', 'extent'),        #HQQ
+    ('unsigned int'  , 'status'))        #I
+
+types.struct('blkif_be_vbd_shrink_t', 
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'blkif_handle'),
+    ('blkif_vdev_t',   'vdevice'),
+    ('unsigned int',   'status'))
+
+types.struct('blkif_be_driver_status_changed_t',
+    ('unsigned int',   'status'),
+    ('unsigned int',   'nr_interfaces'))
+
+types.struct('netif_fe_interface_status_changed_t',
+    ('unsigned int',   'handle'),
+    ('unsigned int',   'status'),
+    ('unsigned int',   'evtchn'),
+    ('u8[6]',          'mac'))
+
+types.struct('netif_fe_driver_status_changed_t',
+    ('unsigned int',   'status'),
+    ('unsigned int',   'nr_interfaces'))
+
+types.struct('netif_fe_interface_connect_t',
+    ('unsigned int',   'handle'),
+    ('unsigned long',  'tx_shmem_frame'),
+    ('unsigned long',  'rx_shmem_frame'))
+
+types.struct('netif_fe_interface_disconnect_t',
+    ('unsigned int',   'handle'))
+
+types.struct('netif_be_create_t', 
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'netif_handle'),
+    ('u8[6]'       ,   'mac'),
+    ('unsigned int',   'status'))
+
+types.struct('netif_be_destroy_t',
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'netif_handle'),
+    ('unsigned int',   'status'))
+
+types.struct('netif_be_connect_t', 
+    ('domid_t'      ,  'domid'),
+    ('unsigned int' ,  'netif_handle'),
+    ('unsigned int' ,  'evtchn'),
+    ('unsigned long',  'tx_shmem_frame'),
+    ('unsigned long',  'rx_shmem_frame'),
+    ('unsigned int' ,  'status'))
+
+types.struct('netif_be_disconnect_t',
+    ('domid_t'     ,   'domid'),
+    ('unsigned int',   'netif_handle'),
+    ('unsigned int',   'status'))
+
+types.struct('netif_be_driver_status_changed_t',
+    ('unsigned int',   'status'),
+    ('unsigned int',   'nr_interfaces'))
+
+if 1 or __name__ == "__main__":
+    types.show()
diff --git a/tools/python/xen/xend/server/domain.py b/tools/python/xen/xend/server/domain.py
new file mode 100644 (file)
index 0000000..ab22234
--- /dev/null
@@ -0,0 +1,41 @@
+import channel
+import controller
+from messages import *
+
+class DomainControllerFactory(controller.ControllerFactory):
+    """Factory for creating domain controllers.
+    """
+
+    def createInstance(self, dom):
+        d = DomainController(self, dom)
+        self.addInstance(d)
+        return d
+    
+    def getInstanceByDom(self, dom):
+        for inst in self.instances.values():
+            if inst.dom == dom:
+                return inst
+        inst = self.createInstance(dom)
+        return inst
+
+
+class DomainController(controller.Controller):
+    """Generic controller for a domain.
+    """
+
+    reasons = {'poweroff' : 'shutdown_poweroff_t',
+               'reboot'   : 'shutdown_reboot_t',
+               'suspend'  : 'shutdown_suspend_t' }
+
+    def __init__(self, factory, dom):
+        controller.Controller.__init__(self, factory, dom)
+        self.majorTypes = [ CMSG_SHUTDOWN ]
+        self.registerChannel()
+        print 'DomainController>', self, self.channel, self.idx
+
+    def shutdown(self, reason):
+        msgtype = self.reasons.get(reason)
+        if not msgtype:
+            raise ValueError('invalid reason:' + reason)
+        msg = packMsg(msgtype, {})
+        self.writeRequest(msg)
diff --git a/tools/python/xen/xend/server/messages.py b/tools/python/xen/xend/server/messages.py
new file mode 100644 (file)
index 0000000..e12d7b6
--- /dev/null
@@ -0,0 +1,219 @@
+import struct
+
+from xen.ext import xu
+
+DEBUG = 0
+
+""" All message formats.
+Added to incrementally for the various message types.
+See below.
+"""
+msg_formats = {}
+
+#============================================================================
+# Console message types.
+#============================================================================
+
+CMSG_CONSOLE  = 0
+
+console_formats = { 'console_data': (CMSG_CONSOLE, 0) }
+
+msg_formats.update(console_formats)
+
+#============================================================================
+# Block interface message types.
+#============================================================================
+
+CMSG_BLKIF_BE = 1
+CMSG_BLKIF_FE = 2
+
+CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED =  0
+CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED    = 32
+CMSG_BLKIF_FE_INTERFACE_CONNECT        = 33
+CMSG_BLKIF_FE_INTERFACE_DISCONNECT     = 34
+
+CMSG_BLKIF_BE_CREATE      = 0
+CMSG_BLKIF_BE_DESTROY     = 1
+CMSG_BLKIF_BE_CONNECT     = 2
+CMSG_BLKIF_BE_DISCONNECT  = 3
+CMSG_BLKIF_BE_VBD_CREATE  = 4
+CMSG_BLKIF_BE_VBD_DESTROY = 5
+CMSG_BLKIF_BE_VBD_GROW    = 6
+CMSG_BLKIF_BE_VBD_SHRINK  = 7
+CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED    = 32
+
+BLKIF_DRIVER_STATUS_DOWN  = 0
+BLKIF_DRIVER_STATUS_UP    = 1
+
+BLKIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
+BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
+BLKIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
+
+BLKIF_BE_STATUS_OKAY                = 0
+BLKIF_BE_STATUS_ERROR               = 1
+BLKIF_BE_STATUS_INTERFACE_EXISTS    = 2
+BLKIF_BE_STATUS_INTERFACE_NOT_FOUND = 3
+BLKIF_BE_STATUS_INTERFACE_CONNECTED = 4
+BLKIF_BE_STATUS_VBD_EXISTS          = 5
+BLKIF_BE_STATUS_VBD_NOT_FOUND       = 6
+BLKIF_BE_STATUS_OUT_OF_MEMORY       = 7
+BLKIF_BE_STATUS_EXTENT_NOT_FOUND    = 8
+BLKIF_BE_STATUS_MAPPING_ERROR       = 9
+
+blkif_formats = {
+    'blkif_be_connect_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT),
+
+    'blkif_be_create_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE),
+
+    'blkif_be_disconnect_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT),
+
+    'blkif_be_destroy_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY),
+
+    'blkif_be_vbd_create_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE),
+
+    'blkif_be_vbd_grow_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW),
+
+    'blkif_be_vbd_destroy_t':
+    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY),
+
+    'blkif_fe_interface_status_changed_t':
+    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED),
+
+    'blkif_fe_driver_status_changed_t':
+    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED),
+
+    'blkif_fe_interface_connect_t':
+    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT),
+}
+
+msg_formats.update(blkif_formats)
+
+#============================================================================
+# Network interface message types.
+#============================================================================
+
+CMSG_NETIF_BE = 3
+CMSG_NETIF_FE = 4
+
+CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED =  0
+CMSG_NETIF_FE_DRIVER_STATUS_CHANGED    = 32
+CMSG_NETIF_FE_INTERFACE_CONNECT        = 33
+CMSG_NETIF_FE_INTERFACE_DISCONNECT     = 34
+
+CMSG_NETIF_BE_CREATE      = 0
+CMSG_NETIF_BE_DESTROY     = 1
+CMSG_NETIF_BE_CONNECT     = 2
+CMSG_NETIF_BE_DISCONNECT  = 3
+CMSG_NETIF_BE_DRIVER_STATUS_CHANGED    = 32
+
+NETIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
+NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
+NETIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
+
+NETIF_DRIVER_STATUS_DOWN   = 0
+NETIF_DRIVER_STATUS_UP     = 1
+
+netif_formats = {
+    'netif_be_connect_t':
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT),
+
+    'netif_be_create_t':
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE),
+
+    'netif_be_disconnect_t':
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT),
+
+    'netif_be_destroy_t':
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY),
+
+    'netif_be_driver_status_changed_t':
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED),
+
+    'netif_fe_driver_status_changed_t':
+    (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED),
+
+    'netif_fe_interface_connect_t':
+    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT),
+
+    'netif_fe_interface_status_changed_t':
+    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED),
+    }
+
+msg_formats.update(netif_formats)
+
+#============================================================================
+CMSG_SHUTDOWN = 6
+
+CMSG_SHUTDOWN_POWEROFF  = 0
+CMSG_SHUTDOWN_REBOOT    = 1
+CMSG_SHUTDOWN_SUSPEND   = 2
+
+STOPCODE_shutdown       = 0
+STOPCODE_reboot         = 1
+STOPCODE_suspend        = 2
+
+shutdown_formats = {
+    'shutdown_poweroff_t':
+    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_POWEROFF),
+    
+    'shutdown_reboot_t':
+    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_REBOOT),
+
+    'shutdown_suspend_t':
+    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SUSPEND),
+    }
+
+msg_formats.update(shutdown_formats)
+
+#============================================================================
+
+class Msg:
+    pass
+
+def packMsg(ty, params):
+    if DEBUG: print '>packMsg', ty, params
+    (major, minor) = msg_formats[ty]
+    args = {}
+    for (k, v) in params.items():
+        if k == 'mac':
+            for i in range(0, 6):
+                args['mac[%d]' % i] = v[i]
+        else:
+            args[k] = v
+    if DEBUG:
+        for (k, v) in args.items():
+            print 'packMsg>', k, v, type(v)
+    msgid = 0
+    msg = xu.message(major, minor, msgid, args)
+    return msg
+
+def unpackMsg(ty, msg):
+    args = msg.get_payload()
+    mac = [0, 0, 0, 0, 0, 0]
+    macs = []
+    for (k, v) in args.items():
+        if k.startswith('mac['):
+            macs += k
+            i = int(k[4:5])
+            mac[i] = v
+        else:
+            pass
+    if macs:
+        args['mac'] = mac
+        for k in macs:
+            del args[k]
+    if DEBUG: print '<unpackMsg', ty, args
+    return args
+
+def msgTypeName(ty, subty):
+    for (name, info) in msg_formats.items():
+        if info[0] == ty and info[1] == subty:
+            return name
+    return None
+
diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py
new file mode 100755 (executable)
index 0000000..2b01805
--- /dev/null
@@ -0,0 +1,316 @@
+import random
+
+from twisted.internet import defer
+
+from xen.xend import sxp
+from xen.xend import PrettyPrint
+from xen.xend import Vifctl
+
+import channel
+import controller
+from messages import *
+
+class NetifControllerFactory(controller.ControllerFactory):
+    """Factory for creating network interface controllers.
+    Also handles the 'back-end' channel to the device driver domain.
+    """
+
+    def __init__(self):
+        controller.ControllerFactory.__init__(self)
+
+        self.majorTypes = [ CMSG_NETIF_BE ]
+
+        self.subTypes = {
+            CMSG_NETIF_BE_CREATE : self.recv_be_create,
+            CMSG_NETIF_BE_CONNECT: self.recv_be_connect,
+            CMSG_NETIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
+            }
+        self.attached = 1
+        self.registerChannel()
+
+    def createInstance(self, dom, recreate=0):
+        """Create or find the network interface controller for a domain.
+        """
+        #print 'netif>createInstance> dom=', dom
+        netif = self.getInstanceByDom(dom)
+        if netif is None:
+            netif = NetifController(self, dom)
+            self.addInstance(netif)
+        return netif
+
+    def getDomainDevices(self, dom):
+        netif = self.getInstanceByDom(dom)
+        return (netif and netif.getDevices()) or []
+
+    def getDomainDevice(self, dom, vif):
+        netif = self.getInstanceByDom(dom)
+        return (netif and netif.getDevice(vif)) or None
+        
+    def setControlDomain(self, dom, recreate=0):
+        """Set the 'back-end' device driver domain.
+        """
+        if self.dom == dom: return
+        self.deregisterChannel()
+        if not recreate:
+            self.attached = 0
+        self.dom = dom
+        self.registerChannel()
+        #
+        #if xend.netif.be_port.remote_dom != 0:
+        #    xend.netif.recovery = True
+        #    xend.netif.be_port = xend.main.port_from_dom(dom)
+        #
+
+    def getControlDomain(self):
+        return self.dom
+
+    def recv_be_create(self, msg, req):
+        self.callDeferred(0)
+    
+    def recv_be_connect(self, msg, req):
+        val = unpackMsg('netif_be_connect_t', msg)
+        dom = val['domid']
+        vif = val['netif_handle']
+        netif = self.getInstanceByDom(dom)
+        if netif:
+            netif.send_interface_connected(vif)
+        else:
+            print "recv_be_connect> unknown vif=", vif
+            pass
+
+    def recv_be_driver_status_changed(self, msg, req):
+        val = unpackMsg('netif_be_driver_status_changed_t', msg)
+        status = val['status']
+        if status == NETIF_DRIVER_STATUS_UP and not self.attached:
+            # If we are not attached the driver domain was changed, and
+            # this signals the new driver domain is ready.
+            for netif in self.getInstances():
+                netif.reattach_devices()
+            self.attached = 1
+
+##         pl = msg.get_payload()
+##         status = pl['status']
+##         if status == NETIF_DRIVER_STATUS_UP:
+##             if xend.netif.recovery:
+##                 print "New netif backend now UP, notifying guests:"
+##                 for netif_key in interface.list.keys():
+##                     netif = interface.list[netif_key]
+##                     netif.create()
+##                     print "  Notifying %d" % netif.dom
+##                     msg = xu.message(
+##                         CMSG_NETIF_FE,
+##                         CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
+##                         { 'handle' : 0, 'status' : 1 })
+##                     netif.ctrlif_tx_req(xend.main.port_from_dom(netif.dom),msg)
+##                 print "Done notifying guests"
+##                 recovery = False
+                
+class NetDev(controller.Dev):
+    """Info record for a network device.
+    """
+
+    def __init__(self, ctrl, vif, mac):
+        controller.Dev.__init__(self, ctrl)
+        self.vif = vif
+        self.mac = mac
+        self.evtchn = None
+        self.bridge = None
+        self.ipaddr = []
+
+    def sxpr(self):
+        vif = str(self.vif)
+        mac = self.get_mac()
+        val = ['netdev', ['vif', vif], ['mac', mac]]
+        if self.bridge:
+            val.append(['bridge', self.bridge])
+        if self.evtchn:
+            val.append(['evtchn',
+                        self.evtchn['port1'],
+                        self.evtchn['port2']])
+        return val
+
+    def get_vifname(self):
+        return "vif%d.%d" % (self.controller.dom, self.vif)
+
+    def get_mac(self):
+        return ':'.join(map(lambda x: "%x" % x, self.mac))
+
+    def vifctl_params(self):
+        return { 'mac'   : self.get_mac(),
+                 'bridge': self.bridge,
+                 'ipaddr': self.ipaddr }
+
+    def up(self, bridge=None, ipaddr=[]):
+        self.bridge = bridge
+        self.ipaddr = ipaddr
+        Vifctl.up(self.get_vifname(), **self.vifctl_params())
+
+    def down(self):
+        Vifctl.down(self.get_vifname(), **self.vifctl_params())
+
+    def destroy(self):
+        def cb_destroy(val):
+            self.controller.send_be_destroy(self.vif)
+        print 'NetDev>destroy>', 'vif=', self.vif
+        PrettyPrint.prettyprint(self.sxpr())
+        self.down()
+        d = self.controller.factory.addDeferred()
+        d.addCallback(cb_destroy)
+        self.controller.send_be_disconnect(self.vif)
+        #self.controller.send_be_destroy(self.vif)
+        
+
+class NetifController(controller.Controller):
+    """Network interface controller. Handles all network devices for a domain.
+    """
+    
+    def __init__(self, factory, dom):
+        #print 'NetifController> dom=', dom
+        controller.Controller.__init__(self, factory, dom)
+        self.devices = {}
+        
+        self.majorTypes = [ CMSG_NETIF_FE ]
+
+        self.subTypes = {
+            CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
+                self.recv_fe_driver_status_changed,
+            CMSG_NETIF_FE_INTERFACE_CONNECT    :
+                self.recv_fe_interface_connect,
+            }
+        self.registerChannel()
+        #print 'NetifController<', 'dom=', self.dom, 'idx=', self.idx
+
+    def sxpr(self):
+        val = ['netif', ['dom', self.dom]]
+        return val
+    
+    def randomMAC(self):
+        # VIFs get a random MAC address with a "special" vendor id.
+        # 
+        # NB. The vendor is currently an "obsolete" one that used to belong
+        # to DEC (AA-00-00). Using it is probably a bit rude :-)
+        # 
+        # NB2. The first bit of the first random octet is set to zero for
+        # all dynamic MAC addresses. This may allow us to manually specify
+        # MAC addresses for some VIFs with no fear of clashes.
+        mac = [ 0xaa, 0x00, 0x00,
+                random.randint(0x00, 0x7f),
+                random.randint(0x00, 0xff),
+                random.randint(0x00, 0xff) ]
+        return mac
+
+    def lostChannel(self):
+        print 'NetifController>lostChannel>', 'dom=', self.dom
+        #self.destroyDevices()
+        controller.Controller.lostChannel(self)
+
+    def getDevices(self):
+        return self.devices.values()
+
+    def getDevice(self, vif):
+        return self.devices.get(vif)
+
+    def addDevice(self, vif, vmac):
+        if vmac is None:
+            mac = self.randomMAC()
+        else:
+            mac = [ int(x, 16) for x in vmac.split(':') ]
+        if len(mac) != 6: raise ValueError("invalid mac")
+        #print "attach_device>", "vif=", vif, "mac=", mac
+        dev = NetDev(self, vif, mac)
+        self.devices[vif] = dev
+        return dev
+
+    def destroy(self):
+        print 'NetifController>destroy>', 'dom=', self.dom
+        self.destroyDevices()
+        
+    def destroyDevices(self):
+        for dev in self.getDevices():
+            dev.destroy()
+
+    def attachDevice(self, vif, vmac, recreate=0):
+        """Attach a network device.
+        If vmac is None a random mac address is assigned.
+
+        @param vif interface index
+        @param vmac mac address (string)
+        """
+        self.addDevice(vif, vmac)
+        if recreate:
+            d = defer.Deferred()
+            d.callback(self)
+        else:
+            d = self.factory.addDeferred()
+            self.send_be_create(vif)
+        return d
+
+    def reattach_devices(self):
+        """Reattach all devices when the back-end control domain has changed.
+        """
+        d = self.factory.addDeferred()
+        self.send_be_create(vif)
+        self.attach_fe_devices(0)
+
+    def attach_fe_devices(self):
+        for dev in self.devices.values():
+            msg = packMsg('netif_fe_interface_status_changed_t',
+                          { 'handle' : dev.vif,
+                            'status' : NETIF_INTERFACE_STATUS_DISCONNECTED,
+                            'evtchn' : 0,
+                            'mac'    : dev.mac })
+            self.writeRequest(msg)
+    
+    def recv_fe_driver_status_changed(self, msg, req):
+        if not req: return
+        msg = packMsg('netif_fe_driver_status_changed_t',
+                      { 'status'        : NETIF_DRIVER_STATUS_UP,
+                        'nr_interfaces' : len(self.devices) })
+        self.writeRequest(msg)
+        self.attach_fe_devices()
+
+    def recv_fe_interface_connect(self, msg, req):
+        val = unpackMsg('netif_fe_interface_connect_t', msg)
+        dev = self.devices[val['handle']]
+        dev.evtchn = channel.eventChannel(0, self.dom)
+        msg = packMsg('netif_be_connect_t',
+                      { 'domid'          : self.dom,
+                        'netif_handle'   : dev.vif,
+                        'evtchn'         : dev.evtchn['port1'],
+                        'tx_shmem_frame' : val['tx_shmem_frame'],
+                        'rx_shmem_frame' : val['rx_shmem_frame'] })
+        self.factory.writeRequest(msg)
+
+    def send_interface_connected(self, vif):
+        dev = self.devices[vif]
+        msg = packMsg('netif_fe_interface_status_changed_t',
+                      { 'handle' : dev.vif,
+                        'status' : NETIF_INTERFACE_STATUS_CONNECTED,
+                        'evtchn' : dev.evtchn['port2'],
+                        'mac'    : dev.mac })
+        self.writeRequest(msg)
+
+    def send_be_create(self, vif):
+        dev = self.devices[vif]
+        msg = packMsg('netif_be_create_t',
+                      { 'domid'        : self.dom,
+                        'netif_handle' : dev.vif,
+                        'mac'          : dev.mac })
+        self.factory.writeRequest(msg)
+
+    def send_be_disconnect(self, vif):
+        dev = self.devices[vif]
+        msg = packMsg('netif_be_disconnect_t',
+                      { 'domid'        : self.dom,
+                        'netif_handle' : dev.vif })
+        self.factory.writeRequest(msg)
+
+    def send_be_destroy(self, vif):
+        print 'NetifController>send_be_destroy>', 'dom=', self.dom, 'vif=', vif
+        PrettyPrint.prettyprint(self.sxpr())
+        dev = self.devices[vif]
+        del self.devices[vif]
+        msg = packMsg('netif_be_destroy_t',
+                      { 'domid'        : self.dom,
+                        'netif_handle' : vif })
+        self.factory.writeRequest(msg)
diff --git a/tools/python/xen/xend/server/params.py b/tools/python/xen/xend/server/params.py
new file mode 100644 (file)
index 0000000..7949f14
--- /dev/null
@@ -0,0 +1,10 @@
+# The following parameters could be placed in a configuration file.
+PID_FILE  = '/var/run/xend.pid'
+LOG_FILE  = '/var/log/xend.log'
+USER = 'root'
+CONTROL_DIR  = '/var/run/xend'
+MGMT_SOCK    = 'xendsock' # relative to CONTROL_DIR
+EVENT_PORT = 8001
+
+CONSOLE_PORT_BASE = 9600
+
diff --git a/tools/python/xen/xend/sxp.py b/tools/python/xen/xend/sxp.py
new file mode 100644 (file)
index 0000000..01654a2
--- /dev/null
@@ -0,0 +1,580 @@
+#!/usr/bin/python2
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""
+Input-driven parsing for s-expression (sxp) format.
+Create a parser: pin = Parser();
+Then call pin.input(buf) with your input.
+Call pin.input_eof() when done.
+Use pin.read() to see if a value has been parsed, pin.get_val()
+to get a parsed value. You can call ready and get_val at any time -
+you don't have to wait until after calling input_eof.
+
+"""
+from __future__ import generators
+
+import sys
+import types
+import errno
+import string
+from StringIO import StringIO
+
+__all__ = [
+    "mime_type", 
+    "ParseError", 
+    "Parser", 
+    "atomp", 
+    "show", 
+    "show_xml", 
+    "elementp", 
+    "name", 
+    "attributes", 
+    "attribute", 
+    "children", 
+    "child", 
+    "child_at", 
+    "child0", 
+    "child1", 
+    "child2", 
+    "child3", 
+    "child4", 
+    "child_value", 
+    "has_id", 
+    "with_id", 
+    "child_with_id", 
+    "elements", 
+    "parse", 
+    ]
+
+mime_type = "application/sxp"
+
+escapes = {
+    'a': '\a',
+    'b': '\b',
+    't': '\t',
+    'n': '\n',
+    'v': '\v',
+    'f': '\f',
+    'r': '\r',
+    '\\': '\\',
+    '\'': '\'',
+    '\"': '\"'}
+
+k_list_open  = "("
+k_list_close = ")"
+k_attr_open  = "@"
+k_eval       = "!"
+
+escapes_rev = {}
+for k in escapes:
+    escapes_rev[escapes[k]] = k
+
+class ParseError(StandardError):
+
+    def __init__(self, parser, value):
+        self.parser = parser
+        self.value = value
+
+    def __str__(self):
+        return self.value
+
+class ParserState:
+
+    def __init__(self, fn, parent=None):
+        self.parent = parent
+        self.buf = ''
+        self.val = []
+        self.delim = None
+        self.fn = fn
+
+    def push(self, fn):
+        return ParserState(fn, parent=self)
+    
+class Parser:
+
+    def __init__(self):
+        self.error = sys.stderr
+        self.reset()
+
+    def reset(self):
+        self.val = []
+        self.eof = 0
+        self.err = 0
+        self.line_no = 0
+        self.char_no = 0
+        self.state = None
+
+    def push_state(self, fn):
+        self.state = self.state.push(fn)
+
+    def pop_state(self):
+        val = self.state
+        self.state = self.state.parent
+        if self.state and self.state.fn == self.state_start:
+            # Return to start state - produce the value.
+            self.val += self.state.val
+            self.state.val = []
+        return val
+
+    def in_class(self, c, s):
+        return s.find(c) >= 0
+        
+    def in_space_class(self, c):
+        return self.in_class(c, ' \t\n\v\f\r')
+
+    def is_separator(self, c):
+        return self.in_class(c, '{}()<>[]!;')
+
+    def in_comment_class(self, c):
+        return self.in_class(c, '#')
+
+    def in_string_quote_class(self, c):
+        return self.in_class(c, '"\'')
+
+    def in_printable_class(self, c):
+        return self.in_class(c, string.printable)
+
+    def set_error_stream(self, error):
+        self.error = error
+
+    def has_error(self):
+        return self.err > 0
+
+    def at_eof(self):
+        return self.eof
+
+    def input_eof(self):
+        self.eof = 1
+        self.input_char(-1)
+
+    def input(self, buf):
+        if not buf or len(buf) == 0:
+            self.input_eof()
+        else:
+            for c in buf:
+                self.input_char(c)
+
+    def input_char(self, c):
+        if self.at_eof():
+            pass
+        elif c == '\n':
+            self.line_no += 1
+            self.char_no = 0
+        else:
+           self.char_no += 1 
+
+        if self.state is None:
+            self.begin_start(None)
+        self.state.fn(c)
+
+    def ready(self):
+        return len(self.val) > 0
+
+    def get_val(self):
+        v = self.val[0]
+        self.val = self.val[1:]
+        return v
+
+    def get_all(self):
+        return self.val
+
+    def begin_start(self, c):
+        self.state = ParserState(self.state_start)
+
+    def end_start(self):
+        self.val += self.state.val
+        self.pop_state()
+    
+    def state_start(self, c):
+        if self.at_eof():
+            self.end_start()
+        elif self.in_space_class(c):
+            pass
+        elif self.in_comment_class(c):
+            self.begin_comment(c)
+        elif c == k_list_open:
+            self.begin_list(c)
+        elif c == k_list_close:
+            raise ParseError(self, "syntax error: "+c)
+        elif self.in_string_quote_class(c):
+            self.begin_string(c)
+        elif self.in_printable_class(c):
+            self.begin_atom(c)
+        elif c == chr(4):
+            # ctrl-D, EOT: end-of-text.
+            self.input_eof()
+        else:
+            raise ParseError(self, "invalid character: code %d" % ord(c))
+
+    def begin_comment(self, c):
+        self.push_state(self.state_comment)
+        self.state.buf += c
+
+    def end_comment(self):
+        self.pop_state()
+    
+    def state_comment(self, c):
+        if c == '\n' or self.at_eof():
+            self.end_comment()
+        else:
+            self.state.buf += c
+
+    def begin_string(self, c):
+        self.push_state(self.state_string)
+        self.state.delim = c
+
+    def end_string(self):
+        val = self.state.buf
+        self.state.parent.val.append(val)
+        self.pop_state()
+        
+    def state_string(self, c):
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        elif c == self.state.delim:
+            self.end_string()
+        elif c == '\\':
+            self.push_state(self.state_escape)
+        else:
+            self.state.buf += c
+
+    def state_escape(self, c):
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        d = escapes.get(c)
+        if d:
+            self.state.parent.buf += d
+            self.pop_state()
+        elif c == 'x':
+            self.state.fn = self.state_hex
+            self.state.val = 0
+        else:
+            self.state.fn = self.state_octal
+            self.state.val = 0
+            self.input_char(c)
+
+    def state_octal(self, c):
+        def octaldigit(c):
+            self.state.val *= 8
+            self.state.val += ord(c) - ord('0')
+            self.state.buf += c
+            if self.state.val < 0 or self.state.val > 0xff:
+                raise ParseError(self, "invalid octal escape: out of range " + self.state.buf)
+            if len(self.state.buf) == 3:
+               octaldone()
+               
+        def octaldone():
+            d = chr(self.state.val)
+            self.state.parent.buf += d
+            self.pop_state()
+            
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        elif '0' <= c <= '7':
+            octaldigit(c)
+        elif len(self.buf):
+            octaldone()
+            self.input_char(c)
+
+    def state_hex(self, c):
+        def hexdone():
+            d = chr(self.state.val)
+            self.state.parent.buf += d
+            self.pop_state()
+            
+        def hexdigit(c, d):
+            self.state.val *= 16
+            self.state.val += ord(c) - ord(d)
+            self.state.buf += c
+            if self.state.val < 0 or self.state.val > 0xff:
+                raise ParseError(self, "invalid hex escape: out of range " + self.state.buf)
+            if len(self.state.buf) == 2:
+                hexdone()
+            
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        elif '0' <= c <= '9':
+            hexdigit(c, '0')
+        elif 'A' <= c <= 'F':
+            hexdigit(c, 'A')
+        elif 'a' <= c <= 'f':
+            hexdigit(c, 'a')
+        elif len(buf):
+            hexdone()
+            self.input_char(c)
+
+    def begin_atom(self, c):
+        self.push_state(self.state_atom)
+        self.state.buf = c
+
+    def end_atom(self):
+        val = self.state.buf
+        self.state.parent.val.append(val)
+        self.pop_state()
+    
+    def state_atom(self, c):
+        if self.at_eof():
+            self.end_atom()
+        elif (self.is_separator(c) or
+              self.in_space_class(c) or
+              self.in_comment_class(c)):
+            self.end_atom()
+            self.input_char(c)
+        else:
+            self.state.buf += c
+
+    def begin_list(self, c):
+        self.push_state(self.state_list)
+
+    def end_list(self):
+        val = self.state.val
+        self.state.parent.val.append(val)
+        self.pop_state()
+
+    def state_list(self, c):
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        elif c == k_list_close:
+            self.end_list()
+        else:
+            self.state_start(c)
+
+def atomp(sxpr):
+    if sxpr.isalnum() or sxpr == '@':
+        return 1
+    for c in sxpr:
+        if c in string.whitespace: return 0
+        if c in '"\'\\(){}[]<>$#&%^': return 0
+        if c in string.ascii_letters: continue
+        if c in string.digits: continue
+        if c in '.-_:/~': continue
+        return 0
+    return 1
+    
+def show(sxpr, out=sys.stdout):
+    if isinstance(sxpr, types.ListType):
+        out.write(k_list_open)
+        i = 0
+        for x in sxpr:
+            if i: out.write(' ')
+            show(x, out)
+            i += 1
+        out.write(k_list_close)
+    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
+        out.write(sxpr)
+    else:
+        #out.write("'" + str(sxpr) + "'")
+        out.write(repr(str(sxpr)))
+
+def show_xml(sxpr, out=sys.stdout):
+    if isinstance(sxpr, types.ListType):
+        element = name(sxpr)
+        out.write('<%s' % element)
+        for attr in attributes(sxpr):
+            out.write(' %s=%s' % (attr[0], attr[1]))
+        out.write('>')
+        i = 0
+        for x in children(sxpr):
+            if i: out.write(' ')
+            show_xml(x, out)
+            i += 1
+        out.write('</%s>' % element)
+    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
+        out.write(sxpr)
+    else:
+        out.write(str(sxpr))
+
+def elementp(sxpr, elt=None):
+    return (isinstance(sxpr, types.ListType)
+            and len(sxpr)
+            and (None == elt or sxpr[0] == elt))
+
+def name(sxpr):
+    val = None
+    if isinstance(sxpr, types.StringType):
+        val = sxpr
+    elif isinstance(sxpr, types.ListType) and len(sxpr):
+        val = sxpr[0]
+    return val
+
+def attributes(sxpr):
+    val = []
+    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
+        attr = sxpr[1]
+        if elementp(attr, k_attr_open):
+            val = attr[1:]
+    return val
+
+def attribute(sxpr, key, val=None):
+    for x in attributes(sxpr):
+        if x[0] == key:
+            val = x[1]
+            break
+    return val
+
+def children(sxpr, elt=None):
+    val = []
+    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
+        i = 1
+        x = sxpr[i]
+        if elementp(x, k_attr_open):
+            i += 1
+        val = sxpr[i : ]
+    if elt:
+        def iselt(x):
+            return elementp(x, elt)
+        val = filter(iselt, val)
+    return val
+
+def child(sxpr, elt, val=None):
+    for x in children(sxpr):
+        if elementp(x, elt):
+            val = x
+            break
+    return val
+
+def child_at(sxpr, index, val=None):
+    kids = children(sxpr)
+    if len(kids) > index:
+        val = kids[index]
+    return val
+
+def child0(sxpr, val=None):
+    return child_at(sxpr, 0, val)
+
+def child1(sxpr, val=None):
+    return child_at(sxpr, 1, val)
+
+def child2(sxpr, val=None):
+    return child_at(sxpr, 2, val)
+
+def child3(sxpr, val=None):
+    return child_at(sxpr, 3, val)
+
+def child4(sxpr, val=None):
+    return child_at(sxpr, 4, val)
+
+def child_value(sxpr, elt, val=None):
+    kid = child(sxpr, elt)
+    if kid:
+        val = child_at(kid, 0, val)
+    return val
+
+def has_id(sxpr, id):
+    """Test if an s-expression has a given id.
+    """
+    return attribute(sxpr, 'id') == id
+
+def with_id(sxpr, id, val=None):
+    """Find the first s-expression with a given id, at any depth.
+
+    sxpr   s-exp or list
+    id     id
+    val    value if not found (default None)
+
+    return s-exp or val
+    """
+    if isinstance(sxpr, types.ListType):
+        for n in sxpr:
+            if has_id(n, id):
+                val = n
+                break
+            v = with_id(n, id)
+            if v is None: continue
+            val = v
+            break
+    return val
+
+def child_with_id(sxpr, id, val=None):
+    """Find the first child with a given id.
+
+    sxpr   s-exp or list
+    id     id
+    val    value if not found (default None)
+
+    return s-exp or val
+    """
+    if isinstance(sxpr, types.ListType):
+        for n in sxpr:
+            if has_id(n, id):
+                val = n
+                break
+    return val
+
+def elements(sxpr, ctxt=None):
+    """Generate elements (at any depth).
+    Visit elements in pre-order.
+    Values generated are (node, context)
+    The context is None if there is no parent, otherwise
+    (index, parent, context) where index is the node's index w.r.t its parent,
+    and context is the parent's context.
+
+    sxpr   s-exp
+
+    returns generator
+    """
+    yield (sxpr, ctxt)
+    i = 0
+    for n in children(sxpr):
+        if isinstance(n, types.ListType):
+            # Calling elements() recursively does not generate recursively,
+            # it just returns a generator object. So we must iterate over it.
+            for v in elements(n, (i, sxpr, ctxt)):
+                yield v
+        i += 1
+
+def to_string(sxpr):
+    """Convert an sxpr to a string.
+
+    sxpr sxpr
+    returns string
+    """
+    io = StringIO()
+    show(sxpr, io)
+    io.seek(0)
+    val = io.getvalue()
+    io.close()
+    return val
+
+def from_string(str):
+    """Create an sxpr by parsing a string.
+
+    str string
+    returns sxpr
+    """
+    io = StringIO(str)
+    return parse(io)
+
+def parse(io):
+    """Completely parse all input from 'io'.
+
+    io input file object
+    returns list of values, None if incomplete
+    raises ParseError on parse error
+    """
+    pin = Parser()
+    while 1:
+        buf = io.readline()
+        pin.input(buf)
+        if len(buf) == 0:
+            break
+    if pin.ready():
+        val = pin.get_all()
+    else:
+        val = None
+    return val
+   
+
+if __name__ == '__main__':
+    print ">main"
+    pin = Parser()
+    while 1:
+        buf = sys.stdin.read(1024)
+        #buf = sys.stdin.readline()
+        pin.input(buf)
+        while pin.ready():
+            val = pin.get_val()
+            print
+            print '****** val=', val
+        if len(buf) == 0:
+            break
+
diff --git a/tools/python/xen/xm/__init__.py b/tools/python/xen/xm/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
new file mode 100644 (file)
index 0000000..12e2e80
--- /dev/null
@@ -0,0 +1,366 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Domain creation.
+"""
+import string
+import sys
+
+from xen.xend import sxp
+from xen.xend import PrettyPrint
+from xen.xend.XendClient import server
+
+from xen.xm.opts import *
+
+gopts = Opts(use="""[options]
+
+Create a domain.
+""")
+
+gopts.opt('help', short='h',
+         fn=set_true, default=0,
+         use="Print this help.")
+
+gopts.opt('quiet', short='q',
+         fn=set_true, default=0,
+         use="Quiet.")
+
+gopts.opt('path', val='PATH',
+         fn=set_value, default='.:/etc/xen',
+         use="Search path for default scripts.")
+
+gopts.opt('defaults', short='f', val='FILE',
+         fn=set_value, default='xmdefaults',
+         use="Use the given default script.")
+
+gopts.opt('config', short='F', val='FILE',
+         fn=set_value, default=None,
+         use='Domain configuration to use (SXP).')
+
+gopts.opt('load', short='L', val='FILE',
+          fn=set_value, default=None,
+          use='Domain saved state to load.')
+
+gopts.opt('define', short='D', val='VAR=VAL',
+         fn=set_var, default=None,
+         use="""Set a variable before loading defaults, e.g. '-D vmid=3'
+         to set vmid. May be repeated to set more thanone variable.""")
+
+gopts.opt('dryrun', short='n',
+         fn=set_true, default=0,
+         use="Dry run - print the config but don't create the domain.")
+
+gopts.opt('name', short='N', val='NAME',
+          fn=set_value, default=None,
+          use="Domain name.")
+
+gopts.opt('console', short='c',
+         fn=set_true, default=0,
+         use="Connect to console after domain is created.")
+
+gopts.opt('kernel', short='k', val='FILE',
+         fn=set_value, default=None,
+         use="Path to kernel image.")
+
+gopts.opt('ramdisk', short='r', val='FILE',
+         fn=set_value, default='',
+         use="Path to ramdisk.")
+
+gopts.opt('builder', short='b', val='FUNCTION',
+         fn=set_value, default='linux',
+         use="Function to use to build the domain.")
+
+gopts.opt('memory', short='m', val='MEMORY',
+         fn=set_value, default=128,
+         use="Domain memory in MB.")
+
+gopts.opt('blkif',
+          fn=set_true, default=0,
+          use="Make the domain a block device backend.")
+
+gopts.opt('netif',
+          fn=set_true, default=0,
+          use="Make the domain a network interface backend.")
+
+gopts.opt('disk', short='d', val='phy:DEV,VDEV,MODE',
+         fn=append_value, default=[],
+         use="""Add a disk device to a domain. The physical device is DEV, which
+         is exported to the domain as VDEV. The disk is read-only if MODE
+         is 'r', read-write if MODE is 'w'.
+         The option may be repeated to add more than one disk.
+         """)
+
+gopts.opt('pci', val='BUS,DEV,FUNC',
+         fn=append_value, default=[],
+         use="""Add a PCI device to a domain, using given params (in hex).
+         For example '-pci c0,02,1a'.
+         The option may be repeated to add more than one pci device.
+         """)
+
+gopts.opt('ipaddr', short='i', val="IPADDR",
+         fn=append_value, default=[],
+         use="Add an IP address to the domain.")
+
+gopts.opt('vif', val="mac=MAC,bridge=BRIDGE",
+         fn=append_value, default=[],
+         use="""Add a network interface with the given MAC address and bridge.
+         If mac is not specified a random MAC address is used.
+         If bridge is not specified the default bridge is used.
+         This option may be repeated to add more than one vif.
+         Specifying vifs will increase the number of interfaces as needed.
+         """)
+
+gopts.opt('nics', val="NUM",
+         fn=set_int, default=1,
+         use="""Set the number of network interfaces.
+         Use the vif option to define interface parameters, otherwise
+         defaults are used. Specifying vifs will increase the
+         number of interfaces as needed.
+         """)
+
+gopts.opt('root', short='R', val='DEVICE',
+         fn=set_value, default='',
+         use="""Set the root= parameter on the kernel command line.
+         Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
+
+gopts.opt('extra', short='E', val="ARGS",
+         fn=set_value, default='',
+         use="Set extra arguments to append to the kernel command line.")
+
+gopts.opt('ip', short='I', val='IPADDR',
+         fn=set_value, default='',
+         use="Set the kernel IP interface address.")
+
+gopts.opt('gateway', val="IPADDR",
+         fn=set_value, default='',
+         use="Set the kernel IP gateway.")
+
+gopts.opt('netmask', val="MASK",
+         fn=set_value, default = '',
+         use="Set the kernel IP netmask.")
+
+gopts.opt('hostname', val="NAME",
+         fn=set_value, default='',
+         use="Set the kernel IP hostname.")
+
+gopts.opt('interface', val="INTF",
+         fn=set_value, default="eth0",
+         use="Set the kernel IP interface name.")
+
+gopts.opt('dhcp', val="off|dhcp",
+         fn=set_value, default='off',
+         use="Set the kernel dhcp option.")
+
+gopts.opt('nfs_server', val="IPADDR",
+         fn=set_value, default=None,
+         use="Set the address of the NFS server for NFS root.")
+
+gopts.opt('nfs_root', val="PATH",
+         fn=set_value, default=None,
+         use="Set the path of the root NFS directory.")
+
+def strip(pre, s):
+    """Strip prefix 'pre' if present.
+    """
+    if s.startswith(pre):
+        return s[len(pre):]
+    else:
+        return s
+
+def configure_image(config, opts):
+    """Create the image config.
+    """
+    config_image = [ opts.builder ]
+    config_image.append([ 'kernel', os.path.abspath(opts.kernel) ])
+    if opts.ramdisk:
+        config_image.append([ 'ramdisk', os.path.abspath(opts.ramdisk) ])
+    if opts.cmdline_ip:
+        cmdline_ip = strip('ip=', opts.cmdline_ip)
+        config_image.append(['ip', cmdline_ip])
+    if opts.root:
+        cmdline_root = strip('root=', opts.root)
+        config_image.append(['root', cmdline_root])
+    if opts.extra:
+        config_image.append(['args', opts.extra])
+    config.append(['image', config_image ])
+    
+def configure_disks(config_devs, opts):
+    """Create the config for disks (virtual block devices).
+    """
+    for (uname, dev, mode) in opts.disk:
+        config_vbd = ['vbd',
+                      ['uname', uname],
+                      ['dev', dev ],
+                      ['mode', mode ] ]
+        config_devs.append(['device', config_vbd])
+
+def configure_pci(config_devs, opts):
+    """Create the config for pci devices.
+    """
+    for (bus, dev, func) in opts.pci:
+        config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
+        config_devs.append(['device', config_pci])
+
+def configure_vifs(config_devs, opts):
+    """Create the config for virtual network interfaces.
+    """
+    vifs = opts.vif
+    vifs_n = max(opts.nics, len(vifs))
+
+    for idx in range(0, vifs_n):
+        if idx < len(vifs):
+            d = vifs[idx]
+            mac = d.get('mac')
+            bridge = d.get('bridge')
+        else:
+            mac = None
+            bridge = None
+        config_vif = ['vif']
+        if mac:
+            config_vif.append(['mac', mac])
+        if bridge:
+            config_vif.append(['bridge', bridge])
+        config_devs.append(['device', config_vif])
+
+def configure_vfr(config, opts):
+     if not opts.ipaddr: return
+     config_vfr = ['vfr']
+     idx = 0 # No way of saying which IP is for which vif?
+     for ip in opts.ipaddr:
+         config_vfr.append(['vif', ['id', idx], ['ip', ip]])
+     config.append(config_vfr)
+
+
+def make_config(opts):
+    """Create the domain configuration.
+    """
+    
+    config = ['vm',
+              ['name', opts.name ],
+              ['memory', opts.memory ] ]
+    if opts.cpu:
+        config.append(['cpu', opts.cpu])
+    if opts.blkif:
+        config.append(['backend', ['blkif']])
+    if opts.netif:
+        config.append(['backend', ['netif']])
+    
+    configure_image(config, opts)
+    config_devs = []
+    configure_disks(config_devs, opts)
+    configure_pci(config_devs, opts)
+    configure_vifs(config_devs, opts)
+    config += config_devs
+    return config
+
+def preprocess_disk(opts):
+    if not opts.disk: return
+    disk = []
+    for v in opts.disk:
+        d = v.split(',')
+        if len(d) != 3:
+            opts.err('Invalid disk specifier: ' + v)
+        disk.append(d)
+    opts.disk = disk
+
+def preprocess_pci(opts):
+    if not opts.pci: return
+    pci = []
+    for v in opts.pci:
+        d = v.split(',')
+        if len(d) != 3:
+            opts.err('Invalid pci specifier: ' + v)
+        # Components are in hex: add hex specifier.
+        hexd = map(lambda v: '0x'+v, d)
+        pci.append(hexd)
+    opts.pci = pci
+
+def preprocess_vifs(opts):
+    if not opts.vif: return
+    vifs = []
+    for vif in opts.vif:
+        d = {}
+        a = vif.split(',')
+        for b in a:
+            (k, v) = b.strip().split('=')
+            k = k.strip()
+            v = v.strip()
+            if k not in ['mac', 'bridge']:
+                opts.err('Invalid vif specifier: ' + vif)
+            d[k] = v
+        vifs.append(d)
+    opts.vif = vifs
+
+def preprocess_ip(opts):
+    setip = (opts.hostname or opts.netmask
+             or opts.gateway or opts.dhcp or opts.interface)
+    if not setip: return
+    #if not opts
+    ip = (opts.ip
+          + ':'
+          + ':' + opts.gateway
+          + ':' + opts.netmask
+          + ':' + opts.hostname
+          + ':' + opts.interface
+          + ':' + opts.dhcp)
+    opts.cmdline_ip = ip
+
+def preprocess_nfs(opts):
+    if (opts.nfs_root or opts.nfs_server):
+        if (not opts.nfs_root) or (not opts.nfs_server):
+            opts.err('Must set nfs root and nfs server')
+    else:
+        return
+    nfs = 'nfsroot=' + opts.nfs_server + ':' + opts.nfs_root
+    opts.extra = nfs + ' ' + opts.extra
+    
+def preprocess(opts):
+    if not opts.kernel:
+        opts.err("No kernel specified")
+    preprocess_disk(opts)
+    preprocess_pci(opts)
+    preprocess_vifs(opts)
+    preprocess_ip(opts)
+    preprocess_nfs(opts)
+         
+def make_domain(opts, config):
+    """Create, build and start a domain.
+    Returns: [int] the ID of the new domain.
+    """
+    if opts.vals.load:
+        filename = os.path.abspath(opts.vals.load)
+        dominfo = server.xend_domain_restore(filename, config)
+    else:
+        dominfo = server.xend_domain_create(config)
+
+    dom = int(sxp.child_value(dominfo, 'id'))
+    console_info = sxp.child(dominfo, 'console')
+    if console_info:
+        console_port = int(sxp.child_value(console_info, 'port'))
+    else:
+        console_port = None
+    
+    if server.xend_domain_unpause(dom) < 0:
+        server.xend_domain_destroy(dom)
+        opts.err("Failed to start domain %d" % dom)
+    opts.info("Started domain %d, console on port %d"
+              % (dom, console_port))
+    return (dom, console_port)
+
+def main(argv):
+    opts = gopts
+    args = opts.parse(argv)
+    if opts.vals.help:
+        opts.usage()
+        return
+    if opts.vals.config:
+        pass
+    else:
+        opts.load_defaults()
+    preprocess(opts.vals)
+    config = make_config(opts.vals)
+    if opts.vals.dryrun:
+        PrettyPrint.prettyprint(config)
+    else:
+        make_domain(opts, config)
+        
+if __name__ == '__main__':
+    main(sys.argv)
diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py
new file mode 100644 (file)
index 0000000..3ab5d23
--- /dev/null
@@ -0,0 +1,448 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Grand unified management application for Xen.
+"""
+import os
+import os.path
+import sys
+from getopt import getopt
+
+from xen.xend import PrettyPrint
+from xen.xend import sxp
+from xen.xend.XendClient import server
+from xen.xm import create, shutdown
+
+class Prog:
+    """Base class for sub-programs.
+    """
+
+    """Program group it belongs to"""
+    group = 'all'
+    """Program name."""
+    name = '??'
+    """Short program info."""
+    info = ''
+
+    def __init__(self, xm):
+        self.xm = xm
+
+    def err(self, msg):
+        self.xm.err(msg)
+
+    def help(self, args):
+        self.shortHelp(args)
+
+    def shortHelp(self, args):
+        print "%-14s %s" % (self.name, self.info)
+
+    def main(self, args):
+        """Program main entry point.
+        """
+        pass
+
+
+class ProgUnknown(Prog):
+
+    name = 'unknown'
+    info = ''
+    
+    def help(self, args):
+        self.xm.err("Unknown command: %s\nTry '%s help' for more information."
+                    % (args[0], self.xm.name))
+
+    main = help
+
+class Xm:
+    """Main application.
+    """
+
+    def __init__(self):
+        self.name = 'xm'
+        self.unknown = ProgUnknown(self)
+        self.progs = {}
+
+    def err(self, msg):
+        print >>sys.stderr, "Error:", msg
+        sys.exit(1)
+
+    def main(self, args):
+        """Main entry point. Dispatches to the progs.
+        """
+        self.name = args[0]
+        if len(args) < 2:
+            self.err("Missing command\nTry '%s help' for more information."
+                     % self.name)
+        help = self.helparg(args)
+        p = self.getprog(args[1], self.unknown)
+        if help:
+            p.help(args[1:])
+        else:
+            p.main(args[1:])
+
+    def helparg(self, args):
+        for a in args:
+            if a in ['-h', '--help']:
+                return 1
+        return 0
+
+    def prog(self, pklass):
+        """Add a sub-program.
+
+        pklass  program class (Prog subclass)
+        """
+        p = pklass(self)
+        self.progs[p.name] = p
+        return p
+
+    def getprog(self, name, val=None):
+        """Get a sub-program.
+        """
+        return self.progs.get(name, val)
+
+    def proglist(self):
+        """Get a list of sub-programs, ordered by group.
+        """
+        groups = {}
+        for p in self.progs.values():
+            l = groups.get(p.group, [])
+            l.append(p)
+            groups[p.group] = l
+        kl = groups.keys()
+        kl.sort()
+        pl = []
+        for k in kl:
+            l = groups[k]
+            l.sort()
+            pl += l
+        return pl
+        
+# Create the application object, then add the sub-program classes.
+xm = Xm()
+
+class ProgHelp(Prog):
+
+    name = "help"
+    info = "Print help."
+    
+    def help(self, args):
+        if len(args) == 2:
+            name = args[1]
+            p = self.xm.getprog(name)
+            if p:
+                p.help(args[1:])
+            else:
+                print '%s: Unknown command: %s' % (self.name, name)
+        else:
+            for p in self.xm.proglist():
+                p.shortHelp(args)
+            print "\nTry '%s help CMD' for help on CMD" % self.xm.name
+
+    main = help
+
+xm.prog(ProgHelp)
+
+class ProgCreate(Prog):
+
+    group = 'domain'
+    name = "create"
+    info = """Create a domain."""
+
+    def help(self, args):
+        create.main([args[0], '-h'])
+
+    def main(self, args):
+        create.main(args)
+
+xm.prog(ProgCreate)
+
+class ProgSave(Prog):
+    group = 'domain'
+    name = "save"
+    info = """Save domain state (and config) to file."""
+
+    def help(self, args):
+        print args[0], "DOM FILE"
+        print """\nSave domain with id DOM to FILE."""
+        
+    def main(self, args):
+        if len(args) < 3: self.err("%s: Missing arguments" % args[0])
+        dom = args[1]
+        savefile = os.path.abspath(args[2])
+        server.xend_domain_save(dom, savefile)
+
+xm.prog(ProgSave)
+
+class ProgRestore(Prog):
+    group = 'domain'
+    name = "restore"
+    info = """Create a domain from a saved state."""
+
+    def help(self, args):
+        print args[0], "FILE [CONFIG]"
+        print "\nRestore a domain from FILE using configuration CONFIG."
+    
+    def main(self, help, args):
+        if len(args) < 2: self.err("%s: Missing arguments" % args[0])
+        savefile =  os.path.abspath(args[1])
+        if len(args) >= 3:
+            configfile = os.path.abspath(args[2])
+        else:
+            configfile = None
+        info = server.xend_domain_restore(savefile, configfile)
+        PrettyPrint.prettyprint(info)
+
+xm.prog(ProgRestore)
+
+class ProgList(Prog):
+    group = 'domain'
+    name = "list"
+    info = """List info about domains."""
+
+    short_options = 'l'
+    long_options = ['long']
+
+    def help(self, args):
+        if help:
+            print args[0], '[options] [DOM...]'
+            print """\nGet information about domains.
+            Either all domains or the domains given.
+
+            -l, --long   Get more detailed information.
+            """
+            return
+        
+    def main(self, args):
+        use_long = 0
+        (options, params) = getopt(args[1:],
+                                   self.short_options,
+                                   self.long_options)
+        n = len(params)
+        for (k, v) in options:
+            if k in ['-l', '--long']:
+                use_long = 1
+                
+        if n == 0:
+            doms = map(int, server.xend_domains())
+            doms.sort()
+        else:
+            doms = map(int, params)
+            
+        if use_long:
+            self.long_list(doms)
+        else:
+            self.brief_list(doms)
+
+    def brief_list(self, doms):
+        print 'Dom  Name             Mem(MB)  CPU  State  Time(s)'
+        for dom in doms:
+            info = server.xend_domain(dom)
+            d = {}
+            d['dom'] = int(dom)
+            d['name'] = sxp.child_value(info, 'name', '??')
+            d['mem'] = int(sxp.child_value(info, 'memory', '0'))
+            d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
+            d['state'] = sxp.child_value(info, 'state', '??')
+            d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
+            print ("%(dom)-4d %(name)-16s %(mem)7d  %(cpu)3d  %(state)5s  %(cpu_time)7.1f" % d)
+
+    def long_list(self, doms):
+        for dom in doms:
+            info = server.xend_domain(dom)
+            print '\nDomain %d' % dom
+            PrettyPrint.prettyprint(info)
+
+xm.prog(ProgList)
+
+class ProgDestroy(Prog):
+    group = 'domain'
+    name = "destroy"
+    info = """Terminate a domain immediately."""
+
+    def help(self, args):
+        print args[0], 'DOM'
+        print '\nTerminate domain DOM immediately.'
+
+    def main(self, args):
+        if len(args) < 2: self.err("%s: Missing domain" % args[0])
+        dom = args[1]
+        server.xend_domain_destroy(dom)
+
+xm.prog(ProgDestroy)
+
+class ProgShutdown(Prog):
+    group = 'domain'
+    name = "shutdown"
+    info = """Shutdown a domain."""
+
+    def help(self, args):
+        shutdown.main([args[0], '-h'])
+    
+    def main(self, args):
+        shutdown.main(args)
+
+xm.prog(ProgShutdown)
+
+class ProgPause(Prog):
+    group = 'domain'
+    name = "pause"
+    info = """Pause execution of a domain."""
+
+    def help(self, args):
+        print args[0], 'DOM'
+        print '\nPause execution of domain DOM.'
+
+    def main(self, args):
+        if len(args) < 2: self.err("%s: Missing domain" % args[0])
+        dom = args[1]
+        server.xend_domain_pause(dom)
+
+xm.prog(ProgPause)
+
+class ProgUnpause(Prog):
+    group = 'domain'
+    name = "unpause"
+    info = """Unpause a paused domain."""
+
+    def help(self, args):
+        print args[0], 'DOM'
+        print '\nUnpause execution of domain DOM.'
+
+    def main(self, args):
+        if len(args) < 2: self.err("%s: Missing domain" % args[0])
+        dom = args[1]
+        server.xend_domain_unpause(dom)
+
+xm.prog(ProgUnpause)
+
+class ProgPincpu(Prog):
+    group = 'domain'
+    name = "pincpu"
+    info = """Pin a domain to a cpu. """
+
+    def help(self, args):
+        print args[0],'DOM CPU'
+        print '\nPin domain DOM to cpu CPU.'
+
+    def main(self, args):
+        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
+        v = map(int, args[1:3])
+        server.xend_domain_pincpu(*v)
+
+xm.prog(ProgPincpu)
+
+class ProgBvt(Prog):
+    group = 'scheduler'
+    name = "bvt"
+    info = """Set BVT scheduler parameters."""
+    
+    def help(self, args):
+        print args[0], "DOM MCUADV WARP WARPL WARPU"
+        print '\nSet Borrowed Virtual Time scheduler parameters.'
+
+    def main(self, args):
+        if len(args) != 6: self.err("%s: Invalid argument(s)" % args[0])
+        v = map(int, args[1:6])
+        server.xend_domain_cpu_bvt_set(*v)
+
+xm.prog(ProgBvt)
+
+class ProgBvtslice(Prog):
+    group = 'scheduler'
+    name = "bvtslice"
+    info = """Set the BVT scheduler slice."""
+
+    def help(self, args):
+        print args[0], 'SLICE'
+        print '\nSet Borrowed Virtual Time scheduler slice.'
+
+    def main(self, args):
+        if len(args) < 2: self.err('%s: Missing slice' % args[0])
+        server.xend_node_cpu_bvt_slice_set(slice)
+
+xm.prog(ProgBvtslice)
+
+class ProgAtropos(Prog):
+    group = 'scheduler'
+    name= "atropos"
+    info = """Set atropos parameters."""
+
+    def help(self, args):
+        print args[0], "DOM PERIOD SLICE LATENCY XTRATIME"
+        print "\nSet atropos parameters."
+
+    def main(self, args):
+        if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
+        v = map(int, args[1:5])
+        server.xend_domain_cpu_atropos_set(*v)
+
+xm.prog(ProgAtropos)
+
+class ProgRrobin(Prog):
+    group = 'scheduler'
+    name = "rrobin"
+    info = """Set round robin slice."""
+
+    def help(self, args):
+        print args[0], "SLICE"
+        print "\nSet round robin scheduler slice."
+
+    def main(self, args):
+        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
+        rrslice = int(args[1])
+        server.xend_node_rrobin_set(rrslice)
+
+xm.prog(ProgRrobin)
+
+class ProgInfo(Prog):
+    group = 'host'
+    name = "info"
+    info = """Get information about the xen host."""
+
+    def main(self, args):
+        info = server.xend_node()
+        for x in info[1:]:
+            print "%-23s:" % x[0], x[1]
+
+xm.prog(ProgInfo)
+
+class ProgConsoles(Prog):
+    group = 'console'
+    name = "consoles"
+    info = """Get information about domain consoles."""
+
+    def main(self, args):
+        l = server.xend_consoles()
+        print "Dom Port  Id"
+        for x in l:
+            info = server.xend_console(x)
+            d = {}
+            d['dom'] = sxp.child(info, 'dst', ['dst', '?', '?'])[1]
+            d['port'] = sxp.child_value(info, 'port', '?')
+            d['id'] = sxp.child_value(info, 'id', '?')
+            print "%(dom)3s %(port)4s %(id)3s" % d
+
+xm.prog(ProgConsoles)
+
+class ProgConsole(Prog):
+    group = 'console'
+    name = "console"
+    info = """Open a console to a domain."""
+    
+    def help(self, args):
+        print "console DOM"
+        print "\nOpen a console to domain DOM."
+
+    def main(self, args):
+        if len(args) < 2: self.err("%s: Missing domain" % args[0])
+        dom = args[1]
+        info = server.xend_domain(dom)
+        console = sxp.child(info, "console")
+        if not console:
+            self.err("No console information")
+        port = sxp.child_value(console, "port")
+        from xen.util import console_client
+        console_client.connect("localhost", int(port))
+
+xm.prog(ProgConsole)
+
+def main(args):
+    xm.main(args)
diff --git a/tools/python/xen/xm/opts.py b/tools/python/xen/xm/opts.py
new file mode 100644 (file)
index 0000000..eb07936
--- /dev/null
@@ -0,0 +1,340 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Object-oriented command-line option support.
+"""
+from getopt import getopt
+import os
+import os.path
+import sys
+import types
+
+class Opt:
+    """An individual option.
+    """
+    def __init__(self, opts, name, short=None, long=None,
+                 val=None, fn=None, use=None, default=None):
+        """Create an option.
+
+        opts    parent options object
+        name    name of the field it controls
+        short   short (1-char) command line switch (optional)
+        long    long command-line switch. Defaults to option name.
+        val     string used to print option args in help.
+                If val is not specified the option has no arg.
+        fn      function to call when the option is specified.
+        use     usage (help) string
+        default default value if not specified on command-line
+        """
+        self.opts = opts
+        self.name = name
+        self.short = short
+        if long is None:
+            long = name
+        self.long = long
+        self.val = val
+        self.use = use
+        self.default = default
+        self.optkeys = []
+        if self.short:
+            self.optkeys.append('-' + self.short)
+        if self.long:
+            self.optkeys.append('--' + self.long)
+        self.fn = fn
+        self.specified_opt = None
+        self.specified_val = None
+        self.value = None
+        self.set(default)
+
+    def __repr__(self):
+        return self.name + '=' + str(self.specified_val)
+
+    __str__ = __repr__
+
+    def set(self, value):
+        """Set the option value.
+        """
+        self.opts.setopt(self.name, value)
+
+    def get(self):
+        """Get the option value.
+        """
+        return self.opts.getopt(self.name)
+
+    def append(self, value):
+        """Append a value to the option value.
+        """
+        v = self.get() or []
+        v.append(value)
+        self.set(v)
+
+    def short_opt(self):
+        """Short option spec.
+        """
+        if self.short:
+            if self.val:
+                return self.short + ':'
+            else:
+                return self.short
+        else:
+            return None
+
+    def long_opt(self):
+        """Long option spec.
+        """
+        if self.long:
+            if self.val:
+                return self.long + '='
+            else:
+                return self.long
+        else:
+            return None
+
+    def show(self):
+        sep = ''
+        for x in self.optkeys:
+            print sep, x,
+            sep = ','
+        if self.val:
+            print self.val,
+        print
+        if self.use:
+            print '\t',
+            print self.use
+        if self.val:
+            print '\tDefault', self.default or 'None'
+
+    def specify(self, k, v):
+        """Specify the option. Called when the option is set
+        from the command line.
+
+        k  option switch used
+        v  optional value given (if any)
+        """
+        if k in self.optkeys:
+            if self.val is None and v:
+                self.opts.err("Option '%s' does not take a value" % k)
+            self.specified_opt = k
+            self.specified_val = v
+            if self.fn:
+                self.fn(self, k, v)
+            return 1
+        else:
+            return 0
+
+    def specified(self):
+        """Test whether the option has been specified: set
+        from the command line.
+        """
+        return self.specified_opt
+
+class OptVals:
+    """Class to hold option values.
+    """
+    pass
+
+class Opts:
+    """Container for options.
+    """
+    def __init__(self, use=None):
+        """Options constructor.
+
+        use  usage string
+        """
+        self.use = use
+        # List of options.
+        self.options = []
+        # Options indexed by name.
+        self.options_map = {}
+        # Command-line arguments.
+        self.argv = []
+        # Option values.
+        self.vals = OptVals()
+        self.vals.quiet = 0
+        # Variables for default scripts.
+        self.vars = {}
+
+    def __repr__(self):
+        return '\n'.join(map(str, self.options))
+
+    __str__ = __repr__
+
+    def opt(self, name, **args):
+        """Add an option.
+
+        name    option name
+        **args  keyword params for option constructor
+        """
+        x = Opt(self, name, **args)
+        self.options.append(x)
+        self.options_map[name] = x
+        return x
+
+    def setvar(self, var, val):
+        """Set a default script variable.
+        """
+        self.vars[var] = val
+
+    def getvar(self, var):
+        """Get a default script variable.
+        """
+        return self.vars.get(var)
+
+    def option(self, name):
+        """Get an option (object).
+        """
+        return self.options_map.get(name)
+
+    def setopt(self, name, val):
+        """Set an option value.
+        An option can also be set using 'opts.vals.name = val'.
+        """
+        setattr(self.vals, name, val)
+
+    def getopt(self, name):
+        """Get an option value.
+        An option value can also be got using 'opts.vals.name'.
+        """
+        getattr(self.vals, name)
+
+    def specified(self, name):
+        """Test if an option has been specified.
+        """
+        opt = self.option(name)
+        return opt and opt.specified()
+
+    def err(self, msg):
+        """Print an error to stderr and exit.
+        """
+        print >>sys.stderr, "Error:", msg
+        sys.exit(1)
+
+    def info(self, msg):
+        """Print a message to stdout (unless quiet is set).
+        """
+        if self.vals.quiet: return
+        print msg
+
+    def warn(self, msg):
+        """Print a warning to stdout.
+        """
+        print >>sys.stderr, "Warning:", msg
+
+    def parse(self, argv):
+        """Parse arguments argv using the options.
+
+        return remaining arguments
+        """
+        self.argv = argv
+        (vals, args) = getopt(argv[1:], self.short_opts(), self.long_opts())
+        self.args = args
+        for (k, v) in vals:
+            for opt in self.options:
+                if opt.specify(k, v): break
+            else:
+                print >>sys.stderr, "Error: Unknown option:", k
+                self.usage()
+        return args
+
+    def short_opts(self):
+        """Get short options specifier for getopt.
+        """
+        l = []
+        for x in self.options:
+            y = x.short_opt()
+            if not y: continue
+            l.append(y)
+        return ''.join(l)
+
+    def long_opts(self):
+        """Get long options specifier for getopt.
+        """
+        l = []
+        for x in self.options:
+            y = x.long_opt()
+            if not y: continue
+            l.append(y)
+        return l
+
+    def usage(self):
+        print 'Usage: ', self.argv[0], self.use or 'OPTIONS'
+        for opt in self.options:
+            opt.show()
+
+    def load_defaults(self):
+        """Load a defaults script. Assumes these options set:
+        'path'    search path
+        'default' script name
+        """
+        for x in [ '' ] + self.vals.path.split(':'):
+            if x:
+                p = os.path.join(x, self.vals.defaults)
+            else:
+                p = self.vals.defaults
+            if os.path.exists(p):
+                self.load(p)
+                break
+        else:
+            self.err("Cannot open defaults file %s" % self.vals.defaults)
+
+    def load(self, defaults, help=0):
+        """Load a defaults file. Local variables in the file
+        are used to set options with the same names.
+        Variables are not used to set options that are already specified.
+        """
+        # Create global and lobal dicts for the file.
+        # Initialize locals to the vars.
+        # Use exec to do the standard imports and
+        # define variables we are passing to the script.
+        globals = {}
+        locals = {}
+        locals.update(self.vars)
+        cmd = '\n'.join(["import sys",
+                         "import os",
+                         "import os.path",
+                         "import xen.util.ip",
+                         "xm_file = '%s'" % defaults,
+                         "xm_help = %d" % help ])
+        exec cmd in globals, locals
+        execfile(defaults, globals, locals)
+        if help: return
+        # Extract the values set by the script and set the corresponding
+        # options, if not set on the command line.
+        vtypes = [ types.StringType,
+                   types.ListType,
+                   types.IntType,
+                   types.FloatType
+                   ]
+        for (k, v) in locals.items():
+            if self.specified(k): continue
+            if not(type(v) in vtypes): continue
+            self.setopt(k, v)
+
+def set_true(opt, k, v):
+    """Set an option true."""
+    opt.set(1)
+
+def set_false(opt, k, v):
+    """Set an option false."""
+    opt.set(0)
+
+def set_value(opt, k, v):
+    """Set an option to a valoue."""
+    opt.set(v)
+
+def set_int(opt, k, v):
+    """Set an option to an integer value."""
+    try:
+        v = int(v)
+    except:
+        opt.opts.err('Invalid value: ' + str(v))
+    opt.set(v)
+
+def append_value(opt, k, v):
+    """Append a value to a list option."""
+    opt.append(v)
+
+def set_var(opt, k, v):
+    """Set a default script variable.
+    """
+    (var, val) = v.strip().split('=')
+    opt.opts.setvar(var.strip(), val.strip())
+
diff --git a/tools/python/xen/xm/shutdown.py b/tools/python/xen/xm/shutdown.py
new file mode 100644 (file)
index 0000000..aaa3545
--- /dev/null
@@ -0,0 +1,75 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Domain shutdown.
+"""
+import string
+import sys
+import time
+
+from xen.xend.XendClient import server
+from xen.xm.opts import *
+
+gopts = Opts(use="""[options] [DOM]
+
+Shutdown one or more domains gracefully.""")
+
+gopts.opt('help', short='h',
+         fn=set_true, default=0,
+         use="Print this help.")
+
+gopts.opt('all', short='a',
+         fn=set_true, default=0,
+         use="Shutdown all domains.")
+
+gopts.opt('wait', short='w',
+         fn=set_true, default=0,
+         use='Wait for shutdown to complete.')
+
+gopts.opt('norestart', short='n',
+          fn=set_true, default=0,
+          use='Prevent domain restart.')
+
+def shutdown(opts, doms, wait):
+    def domains():
+        return [ int(a) for a in server.xend_domains() ]
+    if doms == None: doms = domains()
+    if 0 in doms:
+        doms.remove(0)
+    for d in doms:
+        server.xend_domain_shutdown(d)
+    if wait:
+        while doms:
+            alive = domains()
+            dead = []
+            for d in doms:
+                if d in alive: continue
+                dead.append(d)
+            for d in dead:
+                opts.info("Domain %d terminated" % d)
+                doms.remove(d)
+            time.sleep(1)
+        opts.info("All domains terminated")
+
+def main_all(opts, args):
+    shutdown(opts, None, opts.vals.wait)
+
+def main_dom(opts, args):
+    if len(args) < 1: opts.err('Missing domain')
+    dom = args[0]
+    try:
+        domid = int(dom)
+    except:
+        opts.err('Invalid domain: ' + dom)
+    shutdown(opts, [ domid ], opts.vals.wait)
+    
+def main(argv):
+    opts = gopts
+    args = opts.parse(argv)
+    if opts.vals.help:
+        opts.usage()
+        return
+    print 'shutdown.main>', len(args), args
+    if opts.vals.all:
+        main_all(opts, args)
+    else:
+        main_dom(opts, args)
+        
diff --git a/tools/xc/Makefile b/tools/xc/Makefile
deleted file mode 100644 (file)
index 04b0e35..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-
-all:
-       $(MAKE) -C lib
-       $(MAKE) -C py
-
-install: all
-       $(MAKE) -C lib install
-       $(MAKE) -C py  install
-
-clean:
-       $(MAKE) -C lib clean
-       $(MAKE) -C py  clean
diff --git a/tools/xc/lib/Makefile b/tools/xc/lib/Makefile
deleted file mode 100644 (file)
index e1fa8dd..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-
-MAJOR    = 1.3
-MINOR    = 0
-SONAME   = libxc.so.$(MAJOR)
-
-CC       = gcc
-
-XEN_ROOT = ../../..
-
-vpath %.h      $(XEN_ROOT)/xen/include/hypervisor-ifs
-INCLUDES += -I $(XEN_ROOT)/xen/include/hypervisor-ifs
-
-vpath %.h      $(XEN_ROOT)/tools/xu/lib
-INCLUDES += -I $(XEN_ROOT)/tools/xu/lib
-
-vpath %h       $(XEN_ROOT)/linux-xen-sparse/include
-INCLUDES += -I $(XEN_ROOT)/linux-xen-sparse/include
-
-vpath %c       $(XEN_ROOT)/tools/lib
-INCLUDES += -I $(XEN_ROOT)/tools/lib
-
-LIB_SRCS :=
-LIB_SRCS += allocate.c
-#LIB_SRCS += enum.c
-LIB_SRCS += file_stream.c
-LIB_SRCS += gzip_stream.c
-#LIB_SRCS += hash_table.c
-LIB_SRCS += iostream.c
-#LIB_SRCS += kernel_stream.c
-#LIB_SRCS += lexis.c
-#LIB_SRCS += lzi_stream.c
-#LIB_SRCS += lzo_stream.c
-#LIB_SRCS += marshal.c
-#LIB_SRCS += socket_stream.c
-#LIB_SRCS += string_stream.c
-#LIB_SRCS += sxpr.c
-#LIB_SRCS += sxpr_parser.c
-LIB_SRCS += sys_net.c
-LIB_SRCS += sys_string.c
-#LIB_SRCS += xdr.c
-
-SRCS     :=
-SRCS     += xc_atropos.c
-SRCS     += xc_bvtsched.c
-SRCS     += xc_domain.c
-SRCS     += xc_evtchn.c
-SRCS     += xc_io.c
-SRCS     += xc_linux_build.c
-SRCS     += xc_linux_restore.c
-SRCS     += xc_linux_save.c
-SRCS     += xc_misc.c
-SRCS     += xc_netbsd_build.c
-SRCS     += xc_physdev.c
-SRCS     += xc_private.c
-SRCS     += xc_rrobin.c
-
-SRCS     += $(LIB_SRCS)
-
-#CFLAGS  += -I../../../xen/include/hypervisor-ifs
-#CFLAGS  += -I../../xu/lib
-#CFLAGS  += -I../../../linux-xen-sparse/include
-
-CFLAGS   += -Wall
-CFLAGS   += -Werror
-CFLAGS   += -g
-CFLAGS   += -O3
-CFLAGS   += -fno-strict-aliasing
-CFLAGS   += $(INCLUDES)
-# Get gcc to generate the dependencies for us.
-CFLAGS   += -Wp,-MD,.$(@F).d
-DEPS     = .*.d
-
-OBJS     = $(patsubst %.c,%.o,$(SRCS))
-
-LIB      = libxc.so libxc.so.$(MAJOR) libxc.so.$(MAJOR).$(MINOR)
-
-all: check-for-zlib $(LIB)
-
-check-for-zlib:
-       @if [ ! -e /usr/include/zlib.h ]; then \
-       echo "***********************************************************"; \
-       echo "ERROR: install zlib header files (http://www.gzip.org/zlib)"; \
-       echo "***********************************************************"; \
-       false; \
-       fi
-
-install: all
-       mkdir -p $(prefix)/usr/lib
-       mkdir -p $(prefix)/usr/include
-       install -m0755 $(LIB) $(prefix)/usr/lib
-       install -m0644 xc.h $(prefix)/usr/include
-
-clean:
-       $(RM) *.a *.so *.o *.rpm $(LIB)
-       $(RM) *~
-       $(RM) $(DEPS)
-
-rpm: all
-       rm -rf staging
-       mkdir staging
-       mkdir staging/i386
-       rpmbuild --define "staging$$PWD/staging" --define '_builddir.' \
-               --define "_rpmdir$$PWD/staging" -bb rpm.spec
-       mv staging/i386/*.rpm .
-       rm -rf staging
-
-libxc.so:
-       ln -sf libxc.so.$(MAJOR) $@
-libxc.so.$(MAJOR):
-       ln -sf libxc.so.$(MAJOR).$(MINOR) $@
-libxc.so.$(MAJOR).$(MINOR): $(OBJS)
-       $(CC) -Wl,-soname -Wl,$(SONAME) -shared -o $@ $^ -lz
-
-%.o: %.c Makefile
-
-#      $(CC) $(CFLAGS) -o $@ $<
-
--include $(DEPS)
diff --git a/tools/xc/lib/rpm.spec b/tools/xc/lib/rpm.spec
deleted file mode 100644 (file)
index 1b4c5fc..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-Summary: Xen control interface library
-Name: xen-internal-library
-Version: 1.2
-Release: 1
-License: Xen
-Group: Xen
-BuildRoot: %{staging}
-%description
-Library to make it easier to access the Xen control interfaces.
-
-%pre
-%preun
-%install
-install -m 0755 -d $RPM_BUILD_ROOT/lib
-install -m 0755 libxc.a $RPM_BUILD_ROOT/lib/libxc.a
-install -m 0755 libxc.so $RPM_BUILD_ROOT/lib/libxc.so
-install -m 0755 -d $RPM_BUILD_ROOT/include
-install -m 0644 xc.h $RPM_BUILD_ROOT/include/xc.h
-%clean
-%post
-%postun
-%files
-%defattr(-,root,root)
-%dir /lib
-/lib/libxc.a
-/lib/libxc.so
-%dir /include
-/include/xc.h
diff --git a/tools/xc/lib/xc.h b/tools/xc/lib/xc.h
deleted file mode 100644 (file)
index f969260..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/******************************************************************************
- * xc.h
- * 
- * A library for low-level access to the Xen control interfaces.
- * 
- * Copyright (c) 2003, K A Fraser.
- */
-
-#ifndef __XC_H__
-#define __XC_H__
-
-typedef unsigned char      u8;
-typedef unsigned short     u16;
-typedef unsigned long      u32;
-typedef unsigned long long u64;
-typedef signed char        s8;
-typedef signed short       s16;
-typedef signed long        s32;
-typedef signed long long   s64;
-
-/* Obtain or relinquish a handle on the 'xc' library. */
-int xc_interface_open(void);
-int xc_interface_close(int xc_handle);
-
-typedef struct {
-    u32           domid;
-    unsigned int  cpu;
-    unsigned int  dying:1, crashed:1, shutdown:1, 
-                  paused:1, blocked:1, running:1;
-    unsigned int  shutdown_reason; /* only meaningful if shutdown==1 */
-    unsigned long nr_pages;
-    unsigned long shared_info_frame;
-    u64           cpu_time;
-#define XC_DOMINFO_MAXNAME 16
-    char          name[XC_DOMINFO_MAXNAME];
-    unsigned long max_memkb;
-} xc_dominfo_t;
-
-typedef struct xc_shadow_control_stats_st
-{
-    unsigned long fault_count;
-    unsigned long dirty_count;
-    unsigned long dirty_net_count;     
-    unsigned long dirty_block_count;     
-} xc_shadow_control_stats_t;
-
-int xc_domain_create(int xc_handle, 
-                     unsigned int mem_kb, 
-                     const char *name,
-                     int cpu,
-                     u32 *pdomid);
-int xc_domain_pause(int xc_handle, 
-                    u32 domid);
-int xc_domain_unpause(int xc_handle, 
-                      u32 domid);
-int xc_domain_destroy(int xc_handle, 
-                      u32 domid);
-int xc_domain_pincpu(int xc_handle,
-                     u32 domid,
-                     int cpu);
-int xc_domain_getinfo(int xc_handle,
-                      u32 first_domid, 
-                      unsigned int max_doms,
-                      xc_dominfo_t *info);
-
-int xc_shadow_control(int xc_handle,
-                      u32 domid, 
-                      unsigned int sop,
-                      unsigned long *dirty_bitmap,
-                      unsigned long pages,
-                      xc_shadow_control_stats_t *stats);
-
-
-#define XCFLAGS_VERBOSE 1
-#define XCFLAGS_LIVE    2
-#define XCFLAGS_DEBUG   4
-
-struct XcIOContext;
-int xc_linux_save(int xc_handle, struct XcIOContext *ioctxt);
-int xc_linux_restore(int xc_handle, struct XcIOContext *ioctxt);
-
-int xc_linux_build(int xc_handle,
-                   u32 domid,
-                   const char *image_name,
-                   const char *ramdisk_name,
-                   const char *cmdline,
-                   unsigned int control_evtchn,
-                   unsigned long flags);
-
-int xc_netbsd_build(int xc_handle,
-                    u32 domid,
-                    const char *image_name,
-                    const char *cmdline,
-                    unsigned int control_evtchn);
-
-int xc_bvtsched_global_set(int xc_handle,
-                           unsigned long ctx_allow);
-
-int xc_bvtsched_domain_set(int xc_handle,
-                           u32 domid,
-                           unsigned long mcuadv,
-                           unsigned long warp,
-                           unsigned long warpl,
-                           unsigned long warpu);
-
-int xc_bvtsched_global_get(int xc_handle,
-                           unsigned long *ctx_allow);
-
-int xc_bvtsched_domain_get(int xc_handle,
-                           u32 domid,
-                           unsigned long *mcuadv,
-                           unsigned long *warp,
-                           unsigned long *warpl,
-                           unsigned long *warpu);
-
-int xc_atropos_domain_set(int xc_handle,
-                          u32 domid,
-                          u64 period, u64 slice, u64 latency,
-                          int xtratime);
-
-int xc_atropos_domain_get(int xc_handle,
-                          u32 domid,
-                          u64* period, u64 *slice, u64 *latency,
-                          int *xtratime);
-
-int xc_rrobin_global_set(int xc_handle, u64 slice);
-
-int xc_rrobin_global_get(int xc_handle, u64 *slice);
-
-#define DOMID_SELF              (0x7FFFFFFEU)
-
-typedef struct {
-#define EVTCHNSTAT_closed       0  /* Chennel is not in use.                 */
-#define EVTCHNSTAT_unbound      1  /* Channel is not bound to a source.      */
-#define EVTCHNSTAT_interdomain  2  /* Channel is connected to remote domain. */
-#define EVTCHNSTAT_pirq         3  /* Channel is bound to a phys IRQ line.   */
-#define EVTCHNSTAT_virq         4  /* Channel is bound to a virtual IRQ line */
-    int status;
-    union {
-        struct {
-            u32 dom;
-            int port;
-        } interdomain;
-        int pirq;
-        int virq;
-    } u;
-} xc_evtchn_status_t;
-
-int xc_evtchn_bind_interdomain(int xc_handle,
-                               u32 dom1,   /* may be DOMID_SELF */
-                               u32 dom2,   /* may be DOMID_SELF */
-                               int *port1,
-                               int *port2);
-int xc_evtchn_bind_virq(int xc_handle,
-                        int virq,
-                        int *port);
-int xc_evtchn_close(int xc_handle,
-                    u32 dom,   /* may be DOMID_SELF */
-                    int port);
-int xc_evtchn_send(int xc_handle,
-                   int local_port);
-int xc_evtchn_status(int xc_handle,
-                     u32 dom, /* may be DOMID_SELF */
-                     int port,
-                     xc_evtchn_status_t *status);
-
-int xc_physdev_pci_access_modify(int xc_handle,
-                                 u32 domid,
-                                 int bus,
-                                 int dev,
-                                 int func,
-                                 int enable);
-
-int xc_readconsolering(int xc_handle,
-                       char *str, 
-                       unsigned int max_chars, 
-                       int clear);
-
-typedef struct {
-    int ht_per_core;
-    int cores;
-    unsigned long total_pages;
-    unsigned long free_pages;
-    unsigned long cpu_khz;
-} xc_physinfo_t;
-
-int xc_physinfo(int xc_handle,
-                xc_physinfo_t *info);
-
-int xc_domain_setname(int xc_handle,
-                      u32 domid, 
-                      char *name);
-
-int xc_domain_setinitialmem(int xc_handle,
-                            u32 domid, 
-                            unsigned int initial_memkb);
-
-int xc_domain_setmaxmem(int xc_handle,
-                            u32 domid, 
-                            unsigned int max_memkb);
-
-
-#endif /* __XC_H__ */
diff --git a/tools/xc/lib/xc_atropos.c b/tools/xc/lib/xc_atropos.c
deleted file mode 100644 (file)
index 13d07ca..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/******************************************************************************
- * xc_atropos.c
- * 
- * API for manipulating parameters of the Atropos scheduler.
- * 
- * by Mark Williamson, Copyright (c) 2004 Intel Research Cambridge.
- */
-
-#include "xc_private.h"
-
-int xc_atropos_domain_set(int xc_handle,
-                          u32 domid, u64 period, u64 slice, u64 latency,
-                          int xtratime)
-{
-    dom0_op_t op;
-    struct atropos_adjdom *p = &op.u.adjustdom.u.atropos;
-
-    op.cmd = DOM0_ADJUSTDOM;
-    op.u.adjustdom.domain  = (domid_t)domid;
-    op.u.adjustdom.sched_id = SCHED_ATROPOS;
-    op.u.adjustdom.direction = SCHED_INFO_PUT;
-
-    p->nat_period   = period;
-    p->nat_slice    = slice;
-    p->latency  = latency;
-    p->xtratime = xtratime;
-
-    return do_dom0_op(xc_handle, &op);
-}
-
-int xc_atropos_domain_get(int xc_handle, u32 domid, u64 *period,
-                          u64 *slice, u64 *latency, int *xtratime)
-{
-    dom0_op_t op;
-    int ret;
-    struct atropos_adjdom *p = &op.u.adjustdom.u.atropos;
-
-    op.cmd = DOM0_ADJUSTDOM;    
-    op.u.adjustdom.domain = (domid_t)domid;
-    op.u.adjustdom.sched_id = SCHED_ATROPOS;
-    op.u.adjustdom.direction = SCHED_INFO_GET;
-
-    ret = do_dom0_op(xc_handle, &op);
-
-    *period   = p->nat_period;
-    *slice    = p->nat_slice;
-    *latency  = p->latency;
-    *xtratime = p->xtratime;
-
-    return ret;
-}
diff --git a/tools/xc/lib/xc_bvtsched.c b/tools/xc/lib/xc_bvtsched.c
deleted file mode 100644 (file)
index aeaddcf..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/******************************************************************************
- * xc_bvtsched.c
- * 
- * API for manipulating parameters of the Borrowed Virtual Time scheduler.
- * 
- * Copyright (c) 2003, K A Fraser.
- */
-
-#include "xc_private.h"
-
-int xc_bvtsched_global_set(int xc_handle,
-                           unsigned long ctx_allow)
-{
-    dom0_op_t op;
-
-    op.cmd = DOM0_SCHEDCTL;
-    op.u.schedctl.sched_id = SCHED_BVT;
-    op.u.schedctl.direction = SCHED_INFO_PUT;
-    op.u.schedctl.u.bvt.ctx_allow = ctx_allow;
-
-    return do_dom0_op(xc_handle, &op);
-}
-
-int xc_bvtsched_global_get(int xc_handle,
-                           unsigned long *ctx_allow)
-{
-    dom0_op_t op;
-    int ret;
-    
-    op.cmd = DOM0_SCHEDCTL;
-    op.u.schedctl.sched_id = SCHED_BVT;
-    op.u.schedctl.direction = SCHED_INFO_GET;
-
-    ret = do_dom0_op(xc_handle, &op);
-
-    *ctx_allow = op.u.schedctl.u.bvt.ctx_allow;
-
-    return ret;
-}
-
-int xc_bvtsched_domain_set(int xc_handle,
-                           u32 domid,
-                           unsigned long mcuadv,
-                           unsigned long warp,
-                           unsigned long warpl,
-                           unsigned long warpu)
-{
-    dom0_op_t op;
-    struct bvt_adjdom *bvtadj = &op.u.adjustdom.u.bvt;
-
-    op.cmd = DOM0_ADJUSTDOM;
-    op.u.adjustdom.domain  = (domid_t)domid;
-    op.u.adjustdom.sched_id = SCHED_BVT;
-    op.u.adjustdom.direction = SCHED_INFO_PUT;
-
-    bvtadj->mcu_adv = mcuadv;
-    bvtadj->warp    = warp;
-    bvtadj->warpl   = warpl;
-    bvtadj->warpu   = warpu;
-    return do_dom0_op(xc_handle, &op);
-}
-
-
-int xc_bvtsched_domain_get(int xc_handle,
-                           u32 domid,
-                           unsigned long *mcuadv,
-                           unsigned long *warp,
-                           unsigned long *warpl,
-                           unsigned long *warpu)
-{
-    
-    dom0_op_t op;
-    int ret;
-    struct bvt_adjdom *adjptr = &op.u.adjustdom.u.bvt;
-
-    op.cmd = DOM0_ADJUSTDOM;
-    op.u.adjustdom.domain  = (domid_t)domid;
-    op.u.adjustdom.sched_id = SCHED_BVT;
-    op.u.adjustdom.direction = SCHED_INFO_GET;
-
-    ret = do_dom0_op(xc_handle, &op);
-
-    *mcuadv = adjptr->mcu_adv;
-    *warp   = adjptr->warp;
-    *warpl  = adjptr->warpl;
-    *warpu  = adjptr->warpu;
-    return ret;
-}
diff --git a/tools/xc/lib/xc_domain.c b/tools/xc/lib/xc_domain.c
deleted file mode 100644 (file)
index ab83d0c..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/******************************************************************************
- * xc_domain.c
- * 
- * API for manipulating and obtaining information on domains.
- * 
- * Copyright (c) 2003, K A Fraser.
- */
-
-#include "xc_private.h"
-
-int xc_domain_create(int xc_handle,
-                     unsigned int mem_kb, 
-                     const char *name,
-                     int cpu,
-                     u32 *pdomid)
-{
-    int err;
-    dom0_op_t op;
-
-    op.cmd = DOM0_CREATEDOMAIN;
-    op.u.createdomain.memory_kb = mem_kb;
-    strncpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
-    op.u.createdomain.name[MAX_DOMAIN_NAME-1] = '\0';
-    op.u.createdomain.cpu = cpu;
-
-    if ( (err = do_dom0_op(xc_handle, &op)) == 0 )
-        *pdomid = (u32)op.u.createdomain.domain;
-
-    return err;
-}    
-
-
-int xc_domain_pause(int xc_handle, 
-                    u32 domid)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_PAUSEDOMAIN;
-    op.u.pausedomain.domain = (domid_t)domid;
-    return do_dom0_op(xc_handle, &op);
-}    
-
-
-int xc_domain_unpause(int xc_handle,
-                      u32 domid)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_UNPAUSEDOMAIN;
-    op.u.unpausedomain.domain = (domid_t)domid;
-    return do_dom0_op(xc_handle, &op);
-}    
-
-
-int xc_domain_destroy(int xc_handle,
-                      u32 domid)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_DESTROYDOMAIN;
-    op.u.destroydomain.domain = (domid_t)domid;
-    return do_dom0_op(xc_handle, &op);
-}
-
-int xc_domain_pincpu(int xc_handle,
-                     u32 domid, 
-                     int cpu)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_PINCPUDOMAIN;
-    op.u.pincpudomain.domain = (domid_t)domid;
-    op.u.pincpudomain.cpu  = cpu;
-    return do_dom0_op(xc_handle, &op);
-}
-
-
-int xc_domain_getinfo(int xc_handle,
-                      u32 first_domid,
-                      unsigned int max_doms,
-                      xc_dominfo_t *info)
-{
-    unsigned int nr_doms;
-    u32 next_domid = first_domid;
-    dom0_op_t op;
-
-    for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
-    {
-        op.cmd = DOM0_GETDOMAININFO;
-        op.u.getdomaininfo.domain = (domid_t)next_domid;
-        op.u.getdomaininfo.ctxt = NULL; /* no exec context info, thanks. */
-        if ( do_dom0_op(xc_handle, &op) < 0 )
-            break;
-        info->domid   = (u32)op.u.getdomaininfo.domain;
-
-        info->cpu     =
-            (op.u.getdomaininfo.flags>>DOMFLAGS_CPUSHIFT) & DOMFLAGS_CPUMASK;
-
-        info->dying    = !!(op.u.getdomaininfo.flags & DOMFLAGS_DYING);
-        info->crashed  = !!(op.u.getdomaininfo.flags & DOMFLAGS_CRASHED);
-        info->shutdown = !!(op.u.getdomaininfo.flags & DOMFLAGS_SHUTDOWN);
-        info->paused   = !!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED);
-        info->blocked  = !!(op.u.getdomaininfo.flags & DOMFLAGS_BLOCKED);
-        info->running  = !!(op.u.getdomaininfo.flags & DOMFLAGS_RUNNING);
-
-        info->shutdown_reason = 
-            (op.u.getdomaininfo.flags>>DOMFLAGS_SHUTDOWNSHIFT) & 
-            DOMFLAGS_SHUTDOWNMASK;
-
-        info->nr_pages = op.u.getdomaininfo.tot_pages;
-        info->max_memkb = op.u.getdomaininfo.max_pages<<(PAGE_SHIFT-10);
-        info->shared_info_frame = op.u.getdomaininfo.shared_info_frame;
-        info->cpu_time = op.u.getdomaininfo.cpu_time;
-        strncpy(info->name, op.u.getdomaininfo.name, XC_DOMINFO_MAXNAME);
-        info->name[XC_DOMINFO_MAXNAME-1] = '\0';
-
-        next_domid = (u32)op.u.getdomaininfo.domain + 1;
-        info++;
-    }
-
-    return nr_doms;
-}
-
-int xc_domain_getfullinfo(int xc_handle,
-                          u32 domid,
-                          dom0_op_t *op,
-                          full_execution_context_t *ctxt )
-{
-    int rc;
-    op->cmd = DOM0_GETDOMAININFO;
-    op->u.getdomaininfo.domain = (domid_t)domid;
-    op->u.getdomaininfo.ctxt = ctxt;
-
-    rc = do_dom0_op(xc_handle, op);
-    if ( ((u32)op->u.getdomaininfo.domain != domid) && rc > 0 )
-        return -ESRCH;
-    else
-        return rc;
-}
-
-
-int xc_shadow_control(int xc_handle,
-                      u32 domid, 
-                      unsigned int sop,
-                      unsigned long *dirty_bitmap,
-                      unsigned long pages,
-                      xc_shadow_control_stats_t *stats )
-{
-    int rc;
-    dom0_op_t op;
-    op.cmd = DOM0_SHADOW_CONTROL;
-    op.u.shadow_control.domain = (domid_t)domid;
-    op.u.shadow_control.op     = sop;
-    op.u.shadow_control.dirty_bitmap = dirty_bitmap;
-    op.u.shadow_control.pages  = pages;
-
-    rc = do_dom0_op(xc_handle, &op);
-
-    if ( stats )
-        memcpy(stats, &op.u.shadow_control.stats,
-               sizeof(xc_shadow_control_stats_t));
-
-    return (rc == 0) ? op.u.shadow_control.pages : rc;
-}
-
-int xc_domain_setname(int xc_handle,
-                      u32 domid, 
-                      char *name)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_SETDOMAINNAME;
-    op.u.setdomainname.domain = (domid_t)domid;
-    strncpy(op.u.setdomainname.name, name, MAX_DOMAIN_NAME);
-    return do_dom0_op(xc_handle, &op);
-}
-
-int xc_domain_setinitialmem(int xc_handle,
-                            u32 domid, 
-                            unsigned int initial_memkb)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_SETDOMAININITIALMEM;
-    op.u.setdomaininitialmem.domain = (domid_t)domid;
-    op.u.setdomaininitialmem.initial_memkb = initial_memkb;
-    return do_dom0_op(xc_handle, &op);
-}
-
-int xc_domain_setmaxmem(int xc_handle,
-                        u32 domid, 
-                        unsigned int max_memkb)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_SETDOMAINMAXMEM;
-    op.u.setdomainmaxmem.domain = (domid_t)domid;
-    op.u.setdomainmaxmem.max_memkb = max_memkb;
-    return do_dom0_op(xc_handle, &op);
-}
-
diff --git a/tools/xc/lib/xc_elf.h b/tools/xc/lib/xc_elf.h
deleted file mode 100644 (file)
index e0d0c26..0000000
+++ /dev/null
@@ -1,523 +0,0 @@
-/*
- * Copyright (c) 1995, 1996 Erik Theisen.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-typedef u_int8_t       Elf_Byte;
-
-typedef u_int32_t      Elf32_Addr;     /* Unsigned program address */
-typedef u_int32_t      Elf32_Off;      /* Unsigned file offset */
-typedef int32_t                Elf32_Sword;    /* Signed large integer */
-typedef u_int32_t      Elf32_Word;     /* Unsigned large integer */
-typedef u_int16_t      Elf32_Half;     /* Unsigned medium integer */
-
-typedef u_int64_t      Elf64_Addr;
-typedef u_int64_t      Elf64_Off;
-typedef int32_t                Elf64_Shalf;
-
-typedef int32_t                Elf64_Sword;
-typedef u_int32_t      Elf64_Word;
-
-typedef int64_t                Elf64_Sxword;
-typedef u_int64_t      Elf64_Xword;
-
-typedef u_int32_t      Elf64_Half;
-typedef u_int16_t      Elf64_Quarter;
-
-/*
- * e_ident[] identification indexes 
- * See http://www.caldera.com/developers/gabi/2000-07-17/ch4.eheader.html
- */
-#define EI_MAG0                0               /* file ID */
-#define EI_MAG1                1               /* file ID */
-#define EI_MAG2                2               /* file ID */
-#define EI_MAG3                3               /* file ID */
-#define EI_CLASS       4               /* file class */
-#define EI_DATA                5               /* data encoding */
-#define EI_VERSION     6               /* ELF header version */
-#define EI_OSABI       7               /* OS/ABI ID */
-#define EI_ABIVERSION  8               /* ABI version */ 
-#define EI_PAD         9               /* start of pad bytes */
-#define EI_NIDENT      16              /* Size of e_ident[] */
-
-/* e_ident[] magic number */
-#define        ELFMAG0         0x7f            /* e_ident[EI_MAG0] */
-#define        ELFMAG1         'E'             /* e_ident[EI_MAG1] */
-#define        ELFMAG2         'L'             /* e_ident[EI_MAG2] */
-#define        ELFMAG3         'F'             /* e_ident[EI_MAG3] */
-#define        ELFMAG          "\177ELF"       /* magic */
-#define        SELFMAG         4               /* size of magic */
-
-/* e_ident[] file class */
-#define        ELFCLASSNONE    0               /* invalid */
-#define        ELFCLASS32      1               /* 32-bit objs */
-#define        ELFCLASS64      2               /* 64-bit objs */
-#define        ELFCLASSNUM     3               /* number of classes */
-
-/* e_ident[] data encoding */
-#define ELFDATANONE    0               /* invalid */
-#define ELFDATA2LSB    1               /* Little-Endian */
-#define ELFDATA2MSB    2               /* Big-Endian */
-#define ELFDATANUM     3               /* number of data encode defines */
-
-/* e_ident[] Operating System/ABI */
-#define ELFOSABI_SYSV          0       /* UNIX System V ABI */
-#define ELFOSABI_HPUX          1       /* HP-UX operating system */
-#define ELFOSABI_NETBSD                2       /* NetBSD */
-#define ELFOSABI_LINUX         3       /* GNU/Linux */
-#define ELFOSABI_HURD          4       /* GNU/Hurd */
-#define ELFOSABI_86OPEN                5       /* 86Open common IA32 ABI */
-#define ELFOSABI_SOLARIS       6       /* Solaris */
-#define ELFOSABI_MONTEREY      7       /* Monterey */
-#define ELFOSABI_IRIX          8       /* IRIX */
-#define ELFOSABI_FREEBSD       9       /* FreeBSD */
-#define ELFOSABI_TRU64         10      /* TRU64 UNIX */
-#define ELFOSABI_MODESTO       11      /* Novell Modesto */
-#define ELFOSABI_OPENBSD       12      /* OpenBSD */
-#define ELFOSABI_ARM           97      /* ARM */
-#define ELFOSABI_STANDALONE    255     /* Standalone (embedded) application */
-
-/* e_ident */
-#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
-                      (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
-                      (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
-                      (ehdr).e_ident[EI_MAG3] == ELFMAG3)
-
-/* ELF Header */
-typedef struct elfhdr {
-       unsigned char   e_ident[EI_NIDENT]; /* ELF Identification */
-       Elf32_Half      e_type;         /* object file type */
-       Elf32_Half      e_machine;      /* machine */
-       Elf32_Word      e_version;      /* object file version */
-       Elf32_Addr      e_entry;        /* virtual entry point */
-       Elf32_Off       e_phoff;        /* program header table offset */
-       Elf32_Off       e_shoff;        /* section header table offset */
-       Elf32_Word      e_flags;        /* processor-specific flags */
-       Elf32_Half      e_ehsize;       /* ELF header size */
-       Elf32_Half      e_phentsize;    /* program header entry size */
-       Elf32_Half      e_phnum;        /* number of program header entries */
-       Elf32_Half      e_shentsize;    /* section header entry size */
-       Elf32_Half      e_shnum;        /* number of section header entries */
-       Elf32_Half      e_shstrndx;     /* section header table's "section 
-                                          header string table" entry offset */
-} Elf32_Ehdr;
-
-typedef struct {
-       unsigned char   e_ident[EI_NIDENT];     /* Id bytes */
-       Elf64_Quarter   e_type;                 /* file type */
-       Elf64_Quarter   e_machine;              /* machine type */
-       Elf64_Half      e_version;              /* version number */
-       Elf64_Addr      e_entry;                /* entry point */
-       Elf64_Off       e_phoff;                /* Program hdr offset */
-       Elf64_Off       e_shoff;                /* Section hdr offset */
-       Elf64_Half      e_flags;                /* Processor flags */
-       Elf64_Quarter   e_ehsize;               /* sizeof ehdr */
-       Elf64_Quarter   e_phentsize;            /* Program header entry size */
-       Elf64_Quarter   e_phnum;                /* Number of program headers */
-       Elf64_Quarter   e_shentsize;            /* Section header entry size */
-       Elf64_Quarter   e_shnum;                /* Number of section headers */
-       Elf64_Quarter   e_shstrndx;             /* String table index */
-} Elf64_Ehdr;
-
-/* e_type */
-#define ET_NONE                0               /* No file type */
-#define ET_REL         1               /* relocatable file */
-#define ET_EXEC                2               /* executable file */
-#define ET_DYN         3               /* shared object file */
-#define ET_CORE                4               /* core file */
-#define ET_NUM         5               /* number of types */
-#define ET_LOPROC      0xff00          /* reserved range for processor */
-#define ET_HIPROC      0xffff          /*  specific e_type */
-
-/* e_machine */
-#define EM_NONE                0               /* No Machine */
-#define EM_M32         1               /* AT&T WE 32100 */
-#define EM_SPARC       2               /* SPARC */
-#define EM_386         3               /* Intel 80386 */
-#define EM_68K         4               /* Motorola 68000 */
-#define EM_88K         5               /* Motorola 88000 */
-#define EM_486         6               /* Intel 80486 - unused? */
-#define EM_860         7               /* Intel 80860 */
-#define EM_MIPS                8               /* MIPS R3000 Big-Endian only */
-/* 
- * Don't know if EM_MIPS_RS4_BE,
- * EM_SPARC64, EM_PARISC,
- * or EM_PPC are ABI compliant
- */
-#define EM_MIPS_RS4_BE 10              /* MIPS R4000 Big-Endian */
-#define EM_SPARC64     11              /* SPARC v9 64-bit unoffical */
-#define EM_PARISC      15              /* HPPA */
-#define EM_SPARC32PLUS 18              /* Enhanced instruction set SPARC */
-#define EM_PPC         20              /* PowerPC */
-#define EM_ARM         40              /* Advanced RISC Machines ARM */
-#define EM_ALPHA       41              /* DEC ALPHA */
-#define EM_SPARCV9     43              /* SPARC version 9 */
-#define EM_ALPHA_EXP   0x9026          /* DEC ALPHA */
-#define EM_X86_64      62              /* AMD x86-64 architecture */
-#define EM_VAX         75              /* DEC VAX */
-#define EM_NUM         15              /* number of machine types */
-
-/* Version */
-#define EV_NONE                0               /* Invalid */
-#define EV_CURRENT     1               /* Current */
-#define EV_NUM         2               /* number of versions */
-
-/* Section Header */
-typedef struct {
-       Elf32_Word      sh_name;        /* name - index into section header
-                                          string table section */
-       Elf32_Word      sh_type;        /* type */
-       Elf32_Word      sh_flags;       /* flags */
-       Elf32_Addr      sh_addr;        /* address */
-       Elf32_Off       sh_offset;      /* file offset */
-       Elf32_Word      sh_size;        /* section size */
-       Elf32_Word      sh_link;        /* section header table index link */
-       Elf32_Word      sh_info;        /* extra information */
-       Elf32_Word      sh_addralign;   /* address alignment */
-       Elf32_Word      sh_entsize;     /* section entry size */
-} Elf32_Shdr;
-
-typedef struct {
-       Elf64_Half      sh_name;        /* section name */
-       Elf64_Half      sh_type;        /* section type */
-       Elf64_Xword     sh_flags;       /* section flags */
-       Elf64_Addr      sh_addr;        /* virtual address */
-       Elf64_Off       sh_offset;      /* file offset */
-       Elf64_Xword     sh_size;        /* section size */
-       Elf64_Half      sh_link;        /* link to another */
-       Elf64_Half      sh_info;        /* misc info */
-       Elf64_Xword     sh_addralign;   /* memory alignment */
-       Elf64_Xword     sh_entsize;     /* table entry size */
-} Elf64_Shdr;
-
-/* Special Section Indexes */
-#define SHN_UNDEF      0               /* undefined */
-#define SHN_LORESERVE  0xff00          /* lower bounds of reserved indexes */
-#define SHN_LOPROC     0xff00          /* reserved range for processor */
-#define SHN_HIPROC     0xff1f          /*   specific section indexes */
-#define SHN_ABS                0xfff1          /* absolute value */
-#define SHN_COMMON     0xfff2          /* common symbol */
-#define SHN_HIRESERVE  0xffff          /* upper bounds of reserved indexes */
-
-/* sh_type */
-#define SHT_NULL       0               /* inactive */
-#define SHT_PROGBITS   1               /* program defined information */
-#define SHT_SYMTAB     2               /* symbol table section */
-#define SHT_STRTAB     3               /* string table section */
-#define SHT_RELA       4               /* relocation section with addends*/
-#define SHT_HASH       5               /* symbol hash table section */
-#define SHT_DYNAMIC    6               /* dynamic section */
-#define SHT_NOTE       7               /* note section */
-#define SHT_NOBITS     8               /* no space section */
-#define SHT_REL                9               /* relation section without addends */
-#define SHT_SHLIB      10              /* reserved - purpose unknown */
-#define SHT_DYNSYM     11              /* dynamic symbol table section */
-#define SHT_NUM                12              /* number of section types */
-#define SHT_LOPROC     0x70000000      /* reserved range for processor */
-#define SHT_HIPROC     0x7fffffff      /*  specific section header types */
-#define SHT_LOUSER     0x80000000      /* reserved range for application */
-#define SHT_HIUSER     0xffffffff      /*  specific indexes */
-
-/* Section names */
-#define ELF_BSS         ".bss"         /* uninitialized data */
-#define ELF_DATA        ".data"                /* initialized data */
-#define ELF_DEBUG       ".debug"       /* debug */
-#define ELF_DYNAMIC     ".dynamic"     /* dynamic linking information */
-#define ELF_DYNSTR      ".dynstr"      /* dynamic string table */
-#define ELF_DYNSYM      ".dynsym"      /* dynamic symbol table */
-#define ELF_FINI        ".fini"                /* termination code */
-#define ELF_GOT         ".got"         /* global offset table */
-#define ELF_HASH        ".hash"                /* symbol hash table */
-#define ELF_INIT        ".init"                /* initialization code */
-#define ELF_REL_DATA    ".rel.data"    /* relocation data */
-#define ELF_REL_FINI    ".rel.fini"    /* relocation termination code */
-#define ELF_REL_INIT    ".rel.init"    /* relocation initialization code */
-#define ELF_REL_DYN     ".rel.dyn"     /* relocaltion dynamic link info */
-#define ELF_REL_RODATA  ".rel.rodata"  /* relocation read-only data */
-#define ELF_REL_TEXT    ".rel.text"    /* relocation code */
-#define ELF_RODATA      ".rodata"      /* read-only data */
-#define ELF_SHSTRTAB    ".shstrtab"    /* section header string table */
-#define ELF_STRTAB      ".strtab"      /* string table */
-#define ELF_SYMTAB      ".symtab"      /* symbol table */
-#define ELF_TEXT        ".text"                /* code */
-
-
-/* Section Attribute Flags - sh_flags */
-#define SHF_WRITE      0x1             /* Writable */
-#define SHF_ALLOC      0x2             /* occupies memory */
-#define SHF_EXECINSTR  0x4             /* executable */
-#define SHF_MASKPROC   0xf0000000      /* reserved bits for processor */
-                                       /*  specific section attributes */
-
-/* Symbol Table Entry */
-typedef struct elf32_sym {
-       Elf32_Word      st_name;        /* name - index into string table */
-       Elf32_Addr      st_value;       /* symbol value */
-       Elf32_Word      st_size;        /* symbol size */
-       unsigned char   st_info;        /* type and binding */
-       unsigned char   st_other;       /* 0 - no defined meaning */
-       Elf32_Half      st_shndx;       /* section header index */
-} Elf32_Sym;
-
-typedef struct {
-       Elf64_Half      st_name;        /* Symbol name index in str table */
-       Elf_Byte        st_info;        /* type / binding attrs */
-       Elf_Byte        st_other;       /* unused */
-       Elf64_Quarter   st_shndx;       /* section index of symbol */
-       Elf64_Xword     st_value;       /* value of symbol */
-       Elf64_Xword     st_size;        /* size of symbol */
-} Elf64_Sym;
-
-/* Symbol table index */
-#define STN_UNDEF      0               /* undefined */
-
-/* Extract symbol info - st_info */
-#define ELF32_ST_BIND(x)       ((x) >> 4)
-#define ELF32_ST_TYPE(x)       (((unsigned int) x) & 0xf)
-#define ELF32_ST_INFO(b,t)     (((b) << 4) + ((t) & 0xf))
-
-#define ELF64_ST_BIND(x)       ((x) >> 4)
-#define ELF64_ST_TYPE(x)       (((unsigned int) x) & 0xf)
-#define ELF64_ST_INFO(b,t)     (((b) << 4) + ((t) & 0xf))
-
-/* Symbol Binding - ELF32_ST_BIND - st_info */
-#define STB_LOCAL      0               /* Local symbol */
-#define STB_GLOBAL     1               /* Global symbol */
-#define STB_WEAK       2               /* like global - lower precedence */
-#define STB_NUM                3               /* number of symbol bindings */
-#define STB_LOPROC     13              /* reserved range for processor */
-#define STB_HIPROC     15              /*  specific symbol bindings */
-
-/* Symbol type - ELF32_ST_TYPE - st_info */
-#define STT_NOTYPE     0               /* not specified */
-#define STT_OBJECT     1               /* data object */
-#define STT_FUNC       2               /* function */
-#define STT_SECTION    3               /* section */
-#define STT_FILE       4               /* file */
-#define STT_NUM                5               /* number of symbol types */
-#define STT_LOPROC     13              /* reserved range for processor */
-#define STT_HIPROC     15              /*  specific symbol types */
-
-/* Relocation entry with implicit addend */
-typedef struct {
-       Elf32_Addr      r_offset;       /* offset of relocation */
-       Elf32_Word      r_info;         /* symbol table index and type */
-} Elf32_Rel;
-
-/* Relocation entry with explicit addend */
-typedef struct {
-       Elf32_Addr      r_offset;       /* offset of relocation */
-       Elf32_Word      r_info;         /* symbol table index and type */
-       Elf32_Sword     r_addend;
-} Elf32_Rela;
-
-/* Extract relocation info - r_info */
-#define ELF32_R_SYM(i)         ((i) >> 8)
-#define ELF32_R_TYPE(i)                ((unsigned char) (i))
-#define ELF32_R_INFO(s,t)      (((s) << 8) + (unsigned char)(t))
-
-typedef struct {
-       Elf64_Xword     r_offset;       /* where to do it */
-       Elf64_Xword     r_info;         /* index & type of relocation */
-} Elf64_Rel;
-
-typedef struct {
-       Elf64_Xword     r_offset;       /* where to do it */
-       Elf64_Xword     r_info;         /* index & type of relocation */
-       Elf64_Sxword    r_addend;       /* adjustment value */
-} Elf64_Rela;
-
-#define        ELF64_R_SYM(info)       ((info) >> 32)
-#define        ELF64_R_TYPE(info)      ((info) & 0xFFFFFFFF)
-#define ELF64_R_INFO(s,t)      (((s) << 32) + (u_int32_t)(t))
-
-/* Program Header */
-typedef struct {
-       Elf32_Word      p_type;         /* segment type */
-       Elf32_Off       p_offset;       /* segment offset */
-       Elf32_Addr      p_vaddr;        /* virtual address of segment */
-       Elf32_Addr      p_paddr;        /* physical address - ignored? */
-       Elf32_Word      p_filesz;       /* number of bytes in file for seg. */
-       Elf32_Word      p_memsz;        /* number of bytes in mem. for seg. */
-       Elf32_Word      p_flags;        /* flags */
-       Elf32_Word      p_align;        /* memory alignment */
-} Elf32_Phdr;
-
-typedef struct {
-       Elf64_Half      p_type;         /* entry type */
-       Elf64_Half      p_flags;        /* flags */
-       Elf64_Off       p_offset;       /* offset */
-       Elf64_Addr      p_vaddr;        /* virtual address */
-       Elf64_Addr      p_paddr;        /* physical address */
-       Elf64_Xword     p_filesz;       /* file size */
-       Elf64_Xword     p_memsz;        /* memory size */
-       Elf64_Xword     p_align;        /* memory & file alignment */
-} Elf64_Phdr;
-
-/* Segment types - p_type */
-#define PT_NULL                0               /* unused */
-#define PT_LOAD                1               /* loadable segment */
-#define PT_DYNAMIC     2               /* dynamic linking section */
-#define PT_INTERP      3               /* the RTLD */
-#define PT_NOTE                4               /* auxiliary information */
-#define PT_SHLIB       5               /* reserved - purpose undefined */
-#define PT_PHDR                6               /* program header */
-#define PT_NUM         7               /* Number of segment types */
-#define PT_LOPROC      0x70000000      /* reserved range for processor */
-#define PT_HIPROC      0x7fffffff      /*  specific segment types */
-
-/* Segment flags - p_flags */
-#define PF_X           0x1             /* Executable */
-#define PF_W           0x2             /* Writable */
-#define PF_R           0x4             /* Readable */
-#define PF_MASKPROC    0xf0000000      /* reserved bits for processor */
-                                       /*  specific segment flags */
-
-/* Dynamic structure */
-typedef struct {
-       Elf32_Sword     d_tag;          /* controls meaning of d_val */
-       union {
-               Elf32_Word      d_val;  /* Multiple meanings - see d_tag */
-               Elf32_Addr      d_ptr;  /* program virtual address */
-       } d_un;
-} Elf32_Dyn;
-
-typedef struct {
-       Elf64_Xword     d_tag;          /* controls meaning of d_val */
-       union {
-               Elf64_Addr      d_ptr;
-               Elf64_Xword     d_val;
-       } d_un;
-} Elf64_Dyn;
-
-/* Dynamic Array Tags - d_tag */
-#define DT_NULL                0               /* marks end of _DYNAMIC array */
-#define DT_NEEDED      1               /* string table offset of needed lib */
-#define DT_PLTRELSZ    2               /* size of relocation entries in PLT */
-#define DT_PLTGOT      3               /* address PLT/GOT */
-#define DT_HASH                4               /* address of symbol hash table */
-#define DT_STRTAB      5               /* address of string table */
-#define DT_SYMTAB      6               /* address of symbol table */
-#define DT_RELA                7               /* address of relocation table */
-#define DT_RELASZ      8               /* size of relocation table */
-#define DT_RELAENT     9               /* size of relocation entry */
-#define DT_STRSZ       10              /* size of string table */
-#define DT_SYMENT      11              /* size of symbol table entry */
-#define DT_INIT                12              /* address of initialization func. */
-#define DT_FINI                13              /* address of termination function */
-#define DT_SONAME      14              /* string table offset of shared obj */
-#define DT_RPATH       15              /* string table offset of library
-                                          search path */
-#define DT_SYMBOLIC    16              /* start sym search in shared obj. */
-#define DT_REL         17              /* address of rel. tbl. w addends */
-#define DT_RELSZ       18              /* size of DT_REL relocation table */
-#define DT_RELENT      19              /* size of DT_REL relocation entry */
-#define DT_PLTREL      20              /* PLT referenced relocation entry */
-#define DT_DEBUG       21              /* bugger */
-#define DT_TEXTREL     22              /* Allow rel. mod. to unwritable seg */
-#define DT_JMPREL      23              /* add. of PLT's relocation entries */
-#define DT_BIND_NOW    24              /* Bind now regardless of env setting */
-#define DT_NUM         25              /* Number used. */
-#define DT_LOPROC      0x70000000      /* reserved range for processor */
-#define DT_HIPROC      0x7fffffff      /*  specific dynamic array tags */
-       
-/* Standard ELF hashing function */
-unsigned int elf_hash(const unsigned char *name);
-
-/*
- * Note Definitions
- */
-typedef struct {
-       Elf32_Word namesz;
-       Elf32_Word descsz;
-       Elf32_Word type;
-} Elf32_Note;
-
-typedef struct {
-       Elf64_Half namesz;
-       Elf64_Half descsz;
-       Elf64_Half type;
-} Elf64_Note;
-
-
-#if defined(ELFSIZE)
-#define CONCAT(x,y)    __CONCAT(x,y)
-#define ELFNAME(x)     CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
-#define ELFNAME2(x,y)  CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
-#define ELFNAMEEND(x)  CONCAT(x,CONCAT(_elf,ELFSIZE))
-#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
-#endif
-
-#if defined(ELFSIZE) && (ELFSIZE == 32)
-#define Elf_Ehdr       Elf32_Ehdr
-#define Elf_Phdr       Elf32_Phdr
-#define Elf_Shdr       Elf32_Shdr
-#define Elf_Sym                Elf32_Sym
-#define Elf_Rel                Elf32_Rel
-#define Elf_RelA       Elf32_Rela
-#define Elf_Dyn                Elf32_Dyn
-#define Elf_Word       Elf32_Word
-#define Elf_Sword      Elf32_Sword
-#define Elf_Addr       Elf32_Addr
-#define Elf_Off                Elf32_Off
-#define Elf_Nhdr       Elf32_Nhdr
-#define Elf_Note       Elf32_Note
-
-#define ELF_R_SYM      ELF32_R_SYM
-#define ELF_R_TYPE     ELF32_R_TYPE
-#define ELF_R_INFO     ELF32_R_INFO
-#define ELFCLASS       ELFCLASS32
-
-#define ELF_ST_BIND    ELF32_ST_BIND
-#define ELF_ST_TYPE    ELF32_ST_TYPE
-#define ELF_ST_INFO    ELF32_ST_INFO
-
-#define AuxInfo                Aux32Info
-#elif defined(ELFSIZE) && (ELFSIZE == 64)
-#define Elf_Ehdr       Elf64_Ehdr
-#define Elf_Phdr       Elf64_Phdr
-#define Elf_Shdr       Elf64_Shdr
-#define Elf_Sym                Elf64_Sym
-#define Elf_Rel                Elf64_Rel
-#define Elf_RelA       Elf64_Rela
-#define Elf_Dyn                Elf64_Dyn
-#define Elf_Word       Elf64_Word
-#define Elf_Sword      Elf64_Sword
-#define Elf_Addr       Elf64_Addr
-#define Elf_Off                Elf64_Off
-#define Elf_Nhdr       Elf64_Nhdr
-#define Elf_Note       Elf64_Note
-
-#define ELF_R_SYM      ELF64_R_SYM
-#define ELF_R_TYPE     ELF64_R_TYPE
-#define ELF_R_INFO     ELF64_R_INFO
-#define ELFCLASS       ELFCLASS64
-
-#define ELF_ST_BIND    ELF64_ST_BIND
-#define ELF_ST_TYPE    ELF64_ST_TYPE
-#define ELF_ST_INFO    ELF64_ST_INFO
-
-#define AuxInfo                Aux64Info
-#endif
-
diff --git a/tools/xc/lib/xc_evtchn.c b/tools/xc/lib/xc_evtchn.c
deleted file mode 100644 (file)
index 624f5b1..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/******************************************************************************
- * xc_evtchn.c
- * 
- * API for manipulating and accessing inter-domain event channels.
- * 
- * Copyright (c) 2004, K A Fraser.
- */
-
-#include "xc_private.h"
-
-
-static int do_evtchn_op(int xc_handle, evtchn_op_t *op)
-{
-    int ret = -1;
-    privcmd_hypercall_t hypercall;
-
-    hypercall.op     = __HYPERVISOR_event_channel_op;
-    hypercall.arg[0] = (unsigned long)op;
-
-    if ( mlock(op, sizeof(*op)) != 0 )
-    {
-        PERROR("Could not lock memory for Xen hypercall");
-        goto out1;
-    }
-
-    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
-        goto out2;
-
- out2: (void)munlock(op, sizeof(*op));
- out1: return ret;
-}
-
-
-int xc_evtchn_bind_interdomain(int xc_handle,
-                               u32 dom1,
-                               u32 dom2,
-                               int *port1,
-                               int *port2)
-{
-    evtchn_op_t op;
-    int         rc;
-
-    op.cmd = EVTCHNOP_bind_interdomain;
-    op.u.bind_interdomain.dom1 = (domid_t)dom1;
-    op.u.bind_interdomain.dom2 = (domid_t)dom2;
-   
-    if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
-    {
-        if ( port1 != NULL )
-            *port1 = op.u.bind_interdomain.port1;
-        if ( port2 != NULL )
-            *port2 = op.u.bind_interdomain.port2;
-    }
-    
-    return rc;
-}
-
-
-int xc_evtchn_bind_virq(int xc_handle,
-                        int virq,
-                        int *port)
-{
-    evtchn_op_t op;
-    int         rc;
-
-    op.cmd = EVTCHNOP_bind_virq;
-    op.u.bind_virq.virq = (u32)virq;
-   
-    if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
-    {
-        if ( port != NULL )
-            *port = op.u.bind_virq.port;
-    }
-    
-    return rc;
-}
-
-
-int xc_evtchn_close(int xc_handle,
-                    u32 dom,
-                    int port)
-{
-    evtchn_op_t op;
-    op.cmd = EVTCHNOP_close;
-    op.u.close.dom  = (domid_t)dom;
-    op.u.close.port = port;
-    return do_evtchn_op(xc_handle, &op);
-}
-
-
-int xc_evtchn_send(int xc_handle,
-                   int local_port)
-{
-    evtchn_op_t op;
-    op.cmd = EVTCHNOP_send;
-    op.u.send.local_port = local_port;
-    return do_evtchn_op(xc_handle, &op);
-}
-
-
-int xc_evtchn_status(int xc_handle,
-                     u32 dom,
-                     int port,
-                     xc_evtchn_status_t *status)
-{
-    evtchn_op_t op;
-    int         rc;
-
-    op.cmd = EVTCHNOP_status;
-    op.u.status.dom  = (domid_t)dom;
-    op.u.status.port = port;
-   
-    if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
-    {
-        switch ( status->status = op.u.status.status )
-        {
-        case EVTCHNSTAT_interdomain:
-            status->u.interdomain.dom  = (u32)op.u.status.u.interdomain.dom;
-            status->u.interdomain.port = op.u.status.u.interdomain.port;
-            break;
-        case EVTCHNSTAT_pirq:
-            status->u.pirq = op.u.status.u.pirq;
-            break;
-        case EVTCHNSTAT_virq:
-            status->u.virq = op.u.status.u.virq;
-            break;
-        }
-    }
-    
-    return rc;
-}
diff --git a/tools/xc/lib/xc_io.c b/tools/xc/lib/xc_io.c
deleted file mode 100644 (file)
index 7d75ea2..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "xc_io.h"
-
-void xcio_error(XcIOContext *ctxt, const char *msg, ...){
-  va_list args;
-
-  va_start(args, msg);
-  IOStream_vprint(ctxt->info, msg, args);
-  va_end(args);
-}
-
-void xcio_info(XcIOContext *ctxt, const char *msg, ...){
-  va_list args;
-
-  if(!(ctxt->flags & XCFLAGS_VERBOSE)) return;
-  va_start(args, msg);
-  IOStream_vprint(ctxt->info, msg, args);
-  va_end(args);
-}
-
-void xcio_debug(XcIOContext *ctxt, const char *msg, ...){
-  va_list args;
-
-  if(!(ctxt->flags & XCFLAGS_DEBUG)) return;
-  va_start(args, msg);
-  IOStream_vprint(ctxt->info, msg, args);
-  va_end(args);
-}
diff --git a/tools/xc/lib/xc_io.h b/tools/xc/lib/xc_io.h
deleted file mode 100644 (file)
index 37febb5..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef __XC_XC_IO_H__
-#define __XC_XC_IO_H__
-
-#include "xc_private.h"
-#include "iostream.h"
-
-typedef struct XcIOContext {
-    u32 domain;
-    unsigned flags;
-    IOStream *io;
-    IOStream *info;
-    IOStream *err;
-    char *vmconfig;
-    int vmconfig_n;
-} XcIOContext;
-
-static inline int xcio_read(XcIOContext *ctxt, void *buf, int n){
-    int rc;
-
-    rc = IOStream_read(ctxt->io, buf, n);
-    return (rc == n ? 0 : rc);
-}
-
-static inline int xcio_write(XcIOContext *ctxt, void *buf, int n){
-    int rc;
-
-    rc = IOStream_write(ctxt->io, buf, n);
-    return (rc == n ? 0 : rc);
-}
-
-static inline int xcio_flush(XcIOContext *ctxt){
-    return IOStream_flush(ctxt->io);
-}
-
-extern void xcio_error(XcIOContext *ctxt, const char *msg, ...);
-extern void xcio_info(XcIOContext *ctxt, const char *msg, ...);
-
-#define xcio_perror(_ctxt, _msg...) \
-xcio_error(_ctxt, "(errno %d %s)" _msg, errno, strerror(errno), ## _msg)
-
-#endif /* ! __XC_XC_IO_H__ */
-
-
-
diff --git a/tools/xc/lib/xc_linux_build.c b/tools/xc/lib/xc_linux_build.c
deleted file mode 100644 (file)
index ceace01..0000000
+++ /dev/null
@@ -1,675 +0,0 @@
-/******************************************************************************
- * xc_linux_build.c
- */
-
-#include "xc_private.h"
-#define ELFSIZE 32
-#include "xc_elf.h"
-#include <zlib.h>
-
-#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
-#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-
-#define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
-#define round_pgdown(_p)  ((_p)&PAGE_MASK)
-
-static int readelfimage_base_and_size(char *elfbase, 
-                                      unsigned long elfsize,
-                                      unsigned long *pkernstart,
-                                      unsigned long *pkernend,
-                                      unsigned long *pkernentry);
-static int loadelfimage(char *elfbase, int pmh, unsigned long *parray,
-                        unsigned long vstart);
-
-static long get_tot_pages(int xc_handle, u32 domid)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_GETDOMAININFO;
-    op.u.getdomaininfo.domain = (domid_t)domid;
-    op.u.getdomaininfo.ctxt = NULL;
-    return (do_dom0_op(xc_handle, &op) < 0) ? 
-        -1 : op.u.getdomaininfo.tot_pages;
-}
-
-static int get_pfn_list(int xc_handle,
-                        u32 domid, 
-                        unsigned long *pfn_buf, 
-                        unsigned long max_pfns)
-{
-    dom0_op_t op;
-    int ret;
-    op.cmd = DOM0_GETMEMLIST;
-    op.u.getmemlist.domain   = (domid_t)domid;
-    op.u.getmemlist.max_pfns = max_pfns;
-    op.u.getmemlist.buffer   = pfn_buf;
-
-    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
-        return -1;
-
-    ret = do_dom0_op(xc_handle, &op);
-
-    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
-
-    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
-}
-
-static int copy_to_domain_page(int pm_handle,
-                               unsigned long dst_pfn, 
-                               void *src_page)
-{
-    void *vaddr = map_pfn_writeable(pm_handle, dst_pfn);
-    if ( vaddr == NULL )
-        return -1;
-    memcpy(vaddr, src_page, PAGE_SIZE);
-    unmap_pfn(pm_handle, vaddr);
-    return 0;
-}
-
-static int setup_guestos(int xc_handle,
-                         u32 dom,
-                         char *image, unsigned long image_size,
-                         gzFile initrd_gfd, unsigned long initrd_len,
-                         unsigned long nr_pages,
-                         unsigned long *pvsi, unsigned long *pvke,
-                         full_execution_context_t *ctxt,
-                         const char *cmdline,
-                         unsigned long shared_info_frame,
-                         unsigned int control_evtchn,
-                        unsigned long flags)
-{
-    l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
-    l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
-    unsigned long *page_array = NULL;
-    unsigned long l2tab;
-    unsigned long l1tab;
-    unsigned long count, i;
-    extended_start_info_t *start_info;
-    shared_info_t *shared_info;
-    mmu_t *mmu = NULL;
-    int pm_handle=-1, rc;
-
-    unsigned long nr_pt_pages;
-    unsigned long ppt_alloc;
-    unsigned long *physmap, *physmap_e, physmap_pfn;
-
-    unsigned long v_start;
-    unsigned long vkern_start;
-    unsigned long vkern_entry;
-    unsigned long vkern_end;
-    unsigned long vinitrd_start;
-    unsigned long vinitrd_end;
-    unsigned long vphysmap_start;
-    unsigned long vphysmap_end;
-    unsigned long vstartinfo_start;
-    unsigned long vstartinfo_end;
-    unsigned long vstack_start;
-    unsigned long vstack_end;
-    unsigned long vpt_start;
-    unsigned long vpt_end;
-    unsigned long v_end;
-
-    rc = readelfimage_base_and_size(image, image_size, 
-                                    &vkern_start, &vkern_end, &vkern_entry);
-    if ( rc != 0 )
-        goto error_out;
-    
-    /*
-     * Why do we need this? The number of page-table frames depends on the 
-     * size of the bootstrap address space. But the size of the address space 
-     * depends on the number of page-table frames (since each one is mapped 
-     * read-only). We have a pair of simultaneous equations in two unknowns, 
-     * which we solve by exhaustive search.
-     */
-    for ( nr_pt_pages = 2; ; nr_pt_pages++ )
-    {
-        v_start          = vkern_start & ~((1<<22)-1);
-        vinitrd_start    = round_pgup(vkern_end);
-        vinitrd_end      = vinitrd_start + initrd_len;
-        vphysmap_start   = round_pgup(vinitrd_end);
-        vphysmap_end     = vphysmap_start + (nr_pages * sizeof(unsigned long));
-        vpt_start        = round_pgup(vphysmap_end);
-        vpt_end          = vpt_start + (nr_pt_pages * PAGE_SIZE);
-        vstartinfo_start = vpt_end;
-        vstartinfo_end   = vstartinfo_start + PAGE_SIZE;
-        vstack_start     = vstartinfo_end;
-        vstack_end       = vstack_start + PAGE_SIZE;
-        v_end            = (vstack_end + (1<<22)-1) & ~((1<<22)-1);
-        if ( (v_end - vstack_end) < (512 << 10) )
-            v_end += 1 << 22; /* Add extra 4MB to get >= 512kB padding. */
-        if ( (((v_end - v_start) >> L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
-            break;
-    }
-
-    if ( (v_end - v_start) > (nr_pages * PAGE_SIZE) )
-    {
-        printf("Initial guest OS requires too much space\n"
-               "(%luMB is greater than %luMB limit)\n",
-               (v_end-v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20);
-        goto error_out;
-    }
-
-    printf("VIRTUAL MEMORY ARRANGEMENT:\n"
-           " Loaded kernel: %08lx->%08lx\n"
-           " Init. ramdisk: %08lx->%08lx\n"
-           " Phys-Mach map: %08lx->%08lx\n"
-           " Page tables:   %08lx->%08lx\n"
-           " Start info:    %08lx->%08lx\n"
-           " Boot stack:    %08lx->%08lx\n"
-           " TOTAL:         %08lx->%08lx\n",
-           vkern_start, vkern_end, 
-           vinitrd_start, vinitrd_end,
-           vphysmap_start, vphysmap_end,
-           vpt_start, vpt_end,
-           vstartinfo_start, vstartinfo_end,
-           vstack_start, vstack_end,
-           v_start, v_end);
-    printf(" ENTRY ADDRESS: %08lx\n", vkern_entry);
-
-    if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 )
-        goto error_out;
-
-    if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
-    {
-        PERROR("Could not allocate memory");
-        goto error_out;
-    }
-
-    if ( get_pfn_list(xc_handle, dom, page_array, nr_pages) != nr_pages )
-    {
-        PERROR("Could not get the page frame list");
-        goto error_out;
-    }
-
-    loadelfimage(image, pm_handle, page_array, v_start);
-
-    /* Load the initial ramdisk image. */
-    if ( initrd_len != 0 )
-    {
-        for ( i = (vinitrd_start - v_start); 
-              i < (vinitrd_end - v_start); i += PAGE_SIZE )
-        {
-            char page[PAGE_SIZE];
-            if ( gzread(initrd_gfd, page, PAGE_SIZE) == -1 )
-            {
-                PERROR("Error reading initrd image, could not");
-                goto error_out;
-            }
-            copy_to_domain_page(pm_handle, 
-                                page_array[i>>PAGE_SHIFT], page);
-        }
-    }
-
-    if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL )
-        goto error_out;
-
-    /* First allocate page for page dir. */
-    ppt_alloc = (vpt_start - v_start) >> PAGE_SHIFT;
-    l2tab = page_array[ppt_alloc++] << PAGE_SHIFT;
-    ctxt->pt_base = l2tab;
-
-    /* Initialise the page tables. */
-    if ( (vl2tab = map_pfn_writeable(pm_handle, l2tab >> PAGE_SHIFT)) == NULL )
-        goto error_out;
-    memset(vl2tab, 0, PAGE_SIZE);
-    vl2e = &vl2tab[l2_table_offset(v_start)];
-    for ( count = 0; count < ((v_end-v_start)>>PAGE_SHIFT); count++ )
-    {    
-        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
-        {
-            l1tab = page_array[ppt_alloc++] << PAGE_SHIFT;
-            if ( vl1tab != NULL )
-                unmap_pfn(pm_handle, vl1tab);
-            if ( (vl1tab = map_pfn_writeable(pm_handle, 
-                                             l1tab >> PAGE_SHIFT)) == NULL )
-                goto error_out;
-            memset(vl1tab, 0, PAGE_SIZE);
-            vl1e = &vl1tab[l1_table_offset(v_start + (count<<PAGE_SHIFT))];
-            *vl2e++ = l1tab | L2_PROT;
-        }
-
-        *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
-        if ( (count >= ((vpt_start-v_start)>>PAGE_SHIFT)) && 
-             (count <  ((vpt_end  -v_start)>>PAGE_SHIFT)) )
-            *vl1e &= ~_PAGE_RW;
-        vl1e++;
-    }
-    unmap_pfn(pm_handle, vl1tab);
-    unmap_pfn(pm_handle, vl2tab);
-
-    /* Write the phys->machine and machine->phys table entries. */
-    physmap_pfn = (vphysmap_start - v_start) >> PAGE_SHIFT;
-    physmap = physmap_e = 
-        map_pfn_writeable(pm_handle, page_array[physmap_pfn++]);
-    for ( count = 0; count < nr_pages; count++ )
-    {
-        if ( add_mmu_update(xc_handle, mmu,
-                            (page_array[count] << PAGE_SHIFT) | 
-                            MMU_MACHPHYS_UPDATE, count) )
-            goto error_out;
-        *physmap_e++ = page_array[count];
-        if ( ((unsigned long)physmap_e & (PAGE_SIZE-1)) == 0 )
-        {
-            unmap_pfn(pm_handle, physmap);
-            physmap = physmap_e = 
-                map_pfn_writeable(pm_handle, page_array[physmap_pfn++]);
-        }
-    }
-    unmap_pfn(pm_handle, physmap);
-    
-    /*
-     * Pin down l2tab addr as page dir page - causes hypervisor to provide
-     * correct protection for the page
-     */ 
-    if ( add_mmu_update(xc_handle, mmu,
-                        l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L2_TABLE) )
-        goto error_out;
-
-    start_info = map_pfn_writeable(
-        pm_handle, page_array[(vstartinfo_start-v_start)>>PAGE_SHIFT]);
-    memset(start_info, 0, sizeof(*start_info));
-    start_info->nr_pages     = nr_pages;
-    start_info->shared_info  = shared_info_frame << PAGE_SHIFT;
-    start_info->flags        = flags;
-    start_info->pt_base      = vpt_start;
-    start_info->nr_pt_frames = nr_pt_pages;
-    start_info->mfn_list     = vphysmap_start;
-    start_info->domain_controller_evtchn = control_evtchn;
-    if ( initrd_len != 0 )
-    {
-        start_info->mod_start    = vinitrd_start;
-        start_info->mod_len      = initrd_len;
-    }
-    strncpy(start_info->cmd_line, cmdline, MAX_CMDLINE);
-    start_info->cmd_line[MAX_CMDLINE-1] = '\0';
-    unmap_pfn(pm_handle, start_info);
-
-    /* shared_info page starts its life empty. */
-    shared_info = map_pfn_writeable(pm_handle, shared_info_frame);
-    memset(shared_info, 0, sizeof(shared_info_t));
-    /* Mask all upcalls... */
-    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
-        shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
-    unmap_pfn(pm_handle, shared_info);
-
-    /* Send the page update requests down to the hypervisor. */
-    if ( finish_mmu_updates(xc_handle, mmu) )
-        goto error_out;
-
-    free(mmu);
-    (void)close_pfn_mapper(pm_handle);
-    free(page_array);
-
-    *pvsi = vstartinfo_start;
-    *pvke = vkern_entry;
-
-    return 0;
-
- error_out:
-    if ( mmu != NULL )
-        free(mmu);
-    if ( pm_handle >= 0 )
-        (void)close_pfn_mapper(pm_handle);
-    if ( page_array != NULL )
-        free(page_array);
-    return -1;
-}
-
-static unsigned long get_filesz(int fd)
-{
-    u16 sig;
-    u32 _sz = 0;
-    unsigned long sz;
-
-    lseek(fd, 0, SEEK_SET);
-    read(fd, &sig, sizeof(sig));
-    sz = lseek(fd, 0, SEEK_END);
-    if ( sig == 0x8b1f ) /* GZIP signature? */
-    {
-        lseek(fd, -4, SEEK_END);
-        read(fd, &_sz, 4);
-        sz = _sz;
-    }
-    lseek(fd, 0, SEEK_SET);
-
-    return sz;
-}
-
-static char *read_kernel_image(const char *filename, unsigned long *size)
-{
-    int kernel_fd = -1;
-    gzFile kernel_gfd = NULL;
-    char *image = NULL;
-    unsigned int bytes;
-
-    if ( (kernel_fd = open(filename, O_RDONLY)) < 0 )
-    {
-        PERROR("Could not open kernel image");
-        goto out;
-    }
-
-    *size = get_filesz(kernel_fd);
-
-    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
-    {
-        PERROR("Could not allocate decompression state for state file");
-        goto out;
-    }
-
-    if ( (image = malloc(*size)) == NULL )
-    {
-        PERROR("Could not allocate memory for kernel image");
-        goto out;
-    }
-
-    if ( (bytes = gzread(kernel_gfd, image, *size)) != *size )
-    {
-        PERROR("Error reading kernel image, could not"
-               " read the whole image (%d != %ld).", bytes, *size);
-        free(image);
-        image = NULL;
-    }
-
- out:
-    if ( kernel_gfd != NULL )
-        gzclose(kernel_gfd);
-    else if ( kernel_fd >= 0 )
-        close(kernel_fd);
-    return image;
-}
-
-int xc_linux_build(int xc_handle,
-                   u32 domid,
-                   const char *image_name,
-                   const char *ramdisk_name,
-                   const char *cmdline,
-                   unsigned int control_evtchn,
-                   unsigned long flags)
-{
-    dom0_op_t launch_op, op;
-    int initrd_fd = -1;
-    gzFile initrd_gfd = NULL;
-    int rc, i;
-    full_execution_context_t st_ctxt, *ctxt = &st_ctxt;
-    unsigned long nr_pages;
-    char         *image = NULL;
-    unsigned long image_size, initrd_size=0;
-    unsigned long vstartinfo_start, vkern_entry;
-
-    if ( (nr_pages = get_tot_pages(xc_handle, domid)) < 0 )
-    {
-        PERROR("Could not find total pages for domain");
-        goto error_out;
-    }
-
-    if ( (image = read_kernel_image(image_name, &image_size)) == NULL )
-        goto error_out;
-
-    if ( (ramdisk_name != NULL) && (strlen(ramdisk_name) != 0) )
-    {
-        if ( (initrd_fd = open(ramdisk_name, O_RDONLY)) < 0 )
-        {
-            PERROR("Could not open the initial ramdisk image");
-            goto error_out;
-        }
-
-        initrd_size = get_filesz(initrd_fd);
-
-        if ( (initrd_gfd = gzdopen(initrd_fd, "rb")) == NULL )
-        {
-            PERROR("Could not allocate decompression state for initrd");
-            goto error_out;
-        }
-    }
-
-    if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
-    {   
-        PERROR("Unable to mlock ctxt");
-        return 1;
-    }
-
-    op.cmd = DOM0_GETDOMAININFO;
-    op.u.getdomaininfo.domain = (domid_t)domid;
-    op.u.getdomaininfo.ctxt = ctxt;
-    if ( (do_dom0_op(xc_handle, &op) < 0) || 
-         ((u32)op.u.getdomaininfo.domain != domid) )
-    {
-        PERROR("Could not get info on domain");
-        goto error_out;
-    }
-    if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ||
-         (ctxt->pt_base != 0) )
-    {
-        ERROR("Domain is already constructed");
-        goto error_out;
-    }
-
-    if ( setup_guestos(xc_handle, domid, image, image_size, 
-                       initrd_gfd, initrd_size, nr_pages, 
-                       &vstartinfo_start, &vkern_entry,
-                       ctxt, cmdline,
-                       op.u.getdomaininfo.shared_info_frame,
-                       control_evtchn, flags) < 0 )
-    {
-        ERROR("Error constructing guest OS");
-        goto error_out;
-    }
-
-    if ( initrd_fd >= 0 )
-        close(initrd_fd);
-    if ( initrd_gfd )
-        gzclose(initrd_gfd);
-    if ( image != NULL )
-        free(image);
-
-    ctxt->flags = 0;
-
-    /*
-     * Initial register values:
-     *  DS,ES,FS,GS = FLAT_GUESTOS_DS
-     *       CS:EIP = FLAT_GUESTOS_CS:start_pc
-     *       SS:ESP = FLAT_GUESTOS_DS:start_stack
-     *          ESI = start_info
-     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
-     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
-     */
-    ctxt->cpu_ctxt.ds = FLAT_GUESTOS_DS;
-    ctxt->cpu_ctxt.es = FLAT_GUESTOS_DS;
-    ctxt->cpu_ctxt.fs = FLAT_GUESTOS_DS;
-    ctxt->cpu_ctxt.gs = FLAT_GUESTOS_DS;
-    ctxt->cpu_ctxt.ss = FLAT_GUESTOS_DS;
-    ctxt->cpu_ctxt.cs = FLAT_GUESTOS_CS;
-    ctxt->cpu_ctxt.eip = vkern_entry;
-    ctxt->cpu_ctxt.esp = vstartinfo_start;
-    ctxt->cpu_ctxt.esi = vstartinfo_start;
-    ctxt->cpu_ctxt.eflags = (1<<9) | (1<<2);
-
-    /* FPU is set up to default initial state. */
-    memset(ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
-
-    /* Virtual IDT is empty at start-of-day. */
-    for ( i = 0; i < 256; i++ )
-    {
-        ctxt->trap_ctxt[i].vector = i;
-        ctxt->trap_ctxt[i].cs     = FLAT_GUESTOS_CS;
-    }
-    ctxt->fast_trap_idx = 0;
-
-    /* No LDT. */
-    ctxt->ldt_ents = 0;
-    
-    /* Use the default Xen-provided GDT. */
-    ctxt->gdt_ents = 0;
-
-    /* Ring 1 stack is the initial stack. */
-    ctxt->guestos_ss  = FLAT_GUESTOS_DS;
-    ctxt->guestos_esp = vstartinfo_start;
-
-    /* No debugging. */
-    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
-
-    /* No callback handlers. */
-    ctxt->event_callback_cs     = FLAT_GUESTOS_CS;
-    ctxt->event_callback_eip    = 0;
-    ctxt->failsafe_callback_cs  = FLAT_GUESTOS_CS;
-    ctxt->failsafe_callback_eip = 0;
-
-    memset( &launch_op, 0, sizeof(launch_op) );
-
-    launch_op.u.builddomain.domain   = (domid_t)domid;
-    launch_op.u.builddomain.ctxt = ctxt;
-
-    launch_op.cmd = DOM0_BUILDDOMAIN;
-    rc = do_dom0_op(xc_handle, &launch_op);
-    
-    return rc;
-
- error_out:
-    if ( initrd_gfd != NULL )
-        gzclose(initrd_gfd);
-    else if ( initrd_fd >= 0 )
-        close(initrd_fd);
-    if ( image != NULL )
-        free(image);
-
-    return -1;
-}
-
-static inline int is_loadable_phdr(Elf_Phdr *phdr)
-{
-    return ((phdr->p_type == PT_LOAD) &&
-            ((phdr->p_flags & (PF_W|PF_X)) != 0));
-}
-
-static int readelfimage_base_and_size(char *elfbase, 
-                                      unsigned long elfsize,
-                                      unsigned long *pkernstart,
-                                      unsigned long *pkernend,
-                                      unsigned long *pkernentry)
-{
-    Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
-    Elf_Phdr *phdr;
-    Elf_Shdr *shdr;
-    unsigned long kernstart = ~0UL, kernend=0UL;
-    char *shstrtab, *guestinfo;
-    int h;
-
-    if ( !IS_ELF(*ehdr) )
-    {
-        ERROR("Kernel image does not have an ELF header.");
-        return -EINVAL;
-    }
-
-    if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize )
-    {
-        ERROR("ELF program headers extend beyond end of image.");
-        return -EINVAL;
-    }
-
-    if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize )
-    {
-        ERROR("ELF section headers extend beyond end of image.");
-        return -EINVAL;
-    }
-
-    /* Find the section-header strings table. */
-    if ( ehdr->e_shstrndx == SHN_UNDEF )
-    {
-        ERROR("ELF image has no section-header strings table (shstrtab).");
-        return -EINVAL;
-    }
-    shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + 
-                        (ehdr->e_shstrndx*ehdr->e_shentsize));
-    shstrtab = elfbase + shdr->sh_offset;
-    
-    /* Find the special '__xen_guest' section and check its contents. */
-    for ( h = 0; h < ehdr->e_shnum; h++ )
-    {
-        shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + (h*ehdr->e_shentsize));
-        if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 )
-            continue;
-        guestinfo = elfbase + shdr->sh_offset;
-        if ( (strstr(guestinfo, "GUEST_OS=linux") == NULL) ||
-             (strstr(guestinfo, "XEN_VER=1.3") == NULL) )
-        {
-            ERROR("Will only load Linux images built for Xen v1.3");
-            ERROR("Actually saw: '%s'", guestinfo);
-            return -EINVAL;
-        }
-        break;
-    }
-    if ( h == ehdr->e_shnum )
-    {
-        ERROR("Not a Xen-ELF image: '__xen_guest' section not found.");
-        return -EINVAL;
-    }
-
-    for ( h = 0; h < ehdr->e_phnum; h++ ) 
-    {
-        phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
-        if ( !is_loadable_phdr(phdr) )
-            continue;
-        if ( phdr->p_vaddr < kernstart )
-            kernstart = phdr->p_vaddr;
-        if ( (phdr->p_vaddr + phdr->p_memsz) > kernend )
-            kernend = phdr->p_vaddr + phdr->p_memsz;
-    }
-
-    if ( (kernstart > kernend) || 
-         (ehdr->e_entry < kernstart) || 
-         (ehdr->e_entry > kernend) )
-    {
-        ERROR("Malformed ELF image.");
-        return -EINVAL;
-    }
-
-    *pkernstart = kernstart;
-    *pkernend   = kernend;
-    *pkernentry = ehdr->e_entry;
-
-    return 0;
-}
-
-static int loadelfimage(char *elfbase, int pmh, unsigned long *parray,
-                        unsigned long vstart)
-{
-    Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
-    Elf_Phdr *phdr;
-    int h;
-
-    char         *va;
-    unsigned long pa, done, chunksz;
-
-    for ( h = 0; h < ehdr->e_phnum; h++ ) 
-    {
-        phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
-        if ( !is_loadable_phdr(phdr) )
-            continue;
-        
-        for ( done = 0; done < phdr->p_filesz; done += chunksz )
-        {
-            pa = (phdr->p_vaddr + done) - vstart;
-            va = map_pfn_writeable(pmh, parray[pa>>PAGE_SHIFT]);
-            va += pa & (PAGE_SIZE-1);
-            chunksz = phdr->p_filesz - done;
-            if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
-                chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
-            memcpy(va, elfbase + phdr->p_offset + done, chunksz);
-            unmap_pfn(pmh, va);
-        }
-
-        for ( ; done < phdr->p_memsz; done += chunksz )
-        {
-            pa = (phdr->p_vaddr + done) - vstart;
-            va = map_pfn_writeable(pmh, parray[pa>>PAGE_SHIFT]);
-            va += pa & (PAGE_SIZE-1);
-            chunksz = phdr->p_memsz - done;
-            if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
-                chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
-            memset(va, 0, chunksz);
-            unmap_pfn(pmh, va);            
-        }
-    }
-
-    return 0;
-}
-
diff --git a/tools/xc/lib/xc_linux_restore.c b/tools/xc/lib/xc_linux_restore.c
deleted file mode 100644 (file)
index badba75..0000000
+++ /dev/null
@@ -1,600 +0,0 @@
-/******************************************************************************
- * xc_linux_restore.c
- * 
- * Restore the state of a Linux session.
- * 
- * Copyright (c) 2003, K A Fraser.
- */
-
-#include "xc_private.h"
-#include <asm-xen/suspend.h>
-
-#define MAX_BATCH_SIZE 1024
-
-#define DEBUG 0
-
-#if DEBUG
-#define DPRINTF(_f, _a...) printf ( _f , ## _a )
-#else
-#define DPRINTF(_f, _a...) ((void)0)
-#endif
-
-
-static int get_pfn_list(int xc_handle,
-                        u32 domain_id, 
-                        unsigned long *pfn_buf, 
-                        unsigned long max_pfns)
-{
-    dom0_op_t op;
-    int ret;
-    op.cmd = DOM0_GETMEMLIST;
-    op.u.getmemlist.domain   = (domid_t)domain_id;
-    op.u.getmemlist.max_pfns = max_pfns;
-    op.u.getmemlist.buffer   = pfn_buf;
-
-    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
-    {
-        PERROR("Could not lock pfn list buffer");
-        return -1;
-    }    
-
-    ret = do_dom0_op(xc_handle, &op);
-
-    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
-
-    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
-}
-
-/** Read the vmconfig string from the state input.
- * It is stored as a 4-byte count 'n' followed by n bytes.
- * The config data is stored in a new string in 'ioctxt->vmconfig',
- * and is null-terminated. The count is stored in 'ioctxt->vmconfig_n'.
- *
- * @param ioctxt i/o context
- * @return 0 on success, non-zero on error.
- */
-static int read_vmconfig(XcIOContext *ioctxt){
-    int err = -1;
-    if(xcio_read(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))){
-        goto exit;
-    }
-    ioctxt->vmconfig = malloc(ioctxt->vmconfig_n + 1);
-    if(!ioctxt->vmconfig) goto exit;
-    if(xcio_read(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)){
-        goto exit;
-    }
-    ioctxt->vmconfig[ioctxt->vmconfig_n] = '\0';
-    err = 0;
-  exit:
-    if(err){
-        if(ioctxt->vmconfig){
-            free(ioctxt->vmconfig);
-        }
-        ioctxt->vmconfig = NULL;
-        ioctxt->vmconfig_n = 0;
-    }
-    return err;
-}
-
-int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
-{
-    dom0_op_t op;
-    int rc = 1, i, n, k;
-    unsigned long mfn, pfn, xpfn;
-    unsigned int prev_pc, this_pc;
-    u32 dom = ioctxt->domain;
-    int verify = 0; 
-
-    /* Number of page frames in use by this Linux session. */
-    unsigned long nr_pfns;
-
-    /* The new domain's shared-info frame number. */
-    unsigned long shared_info_frame;
-    unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */
-    
-    /* A copy of the CPU context of the guest. */
-    full_execution_context_t ctxt;
-
-    /* First 16 bytes of the state file must contain 'LinuxGuestRecord'. */
-    char signature[16];
-    
-    /* A copy of the domain's name. */
-    char name[MAX_DOMAIN_NAME];
-
-    /* A table containg the type of each PFN (/not/ MFN!). */
-    unsigned long *pfn_type = NULL;
-
-    /* A table of MFNs to map in the current region */
-    unsigned long *region_mfn = NULL;
-
-    /* A temporary mapping, and a copy, of one frame of guest memory. */
-    unsigned long *ppage;
-
-    /* A copy of the pfn-to-mfn table frame list. */
-    unsigned long pfn_to_mfn_frame_list[1024];
-
-    /* A table mapping each PFN to its new MFN. */
-    unsigned long *pfn_to_mfn_table = NULL;
-
-    /* used by mapper for updating the domain's copy of the table */
-    unsigned long *live_pfn_to_mfn_table = NULL;
-
-    /* A temporary mapping of the guest's suspend record. */
-    suspend_record_t *p_srec;
-
-    char *region_base;
-
-    mmu_t *mmu = NULL;
-
-    int pm_handle = -1;
-
-    /* used by debug verify code */
-    unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
-
-    if ( mlock(&ctxt, sizeof(ctxt) ) ) {   
-        /* needed for when we do the build dom0 op, 
-           but might as well do early */
-        PERROR("Unable to mlock ctxt");
-        return 1;
-    }
-
-    /* Start writing out the saved-domain record. */
-    if ( xcio_read(ioctxt, signature, 16) ||
-         (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) {
-        xcio_error(ioctxt, "Unrecognised state format -- no signature found");
-        goto out;
-    }
-
-    if ( xcio_read(ioctxt, name,                  sizeof(name)) ||
-         xcio_read(ioctxt, &nr_pfns,              sizeof(unsigned long)) ||
-         xcio_read(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ) {
-        xcio_error(ioctxt, "Error reading header");
-        goto out;
-    }
-
-    if(read_vmconfig(ioctxt)){
-        xcio_error(ioctxt, "Error writing vmconfig");
-        goto out;
-    }
-
-    for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) {
-        if ( name[i] == '\0' ) break;
-        if ( name[i] & 0x80 )
-        {
-            xcio_error(ioctxt, "Random characters in domain name");
-            goto out;
-        }
-    }
-    name[MAX_DOMAIN_NAME-1] = '\0';
-
-    if ( nr_pfns > 1024*1024 ) {
-        xcio_error(ioctxt, "Invalid state file -- pfn count out of range");
-        goto out;
-    }
-
-    /* We want zeroed memory so use calloc rather than malloc. */
-    pfn_to_mfn_table = calloc(1, 4 * nr_pfns);
-    pfn_type         = calloc(1, 4 * nr_pfns);    
-    region_mfn       = calloc(1, 4 * MAX_BATCH_SIZE);    
-
-    if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) || 
-         (region_mfn == NULL) ) {
-        errno = ENOMEM;
-        goto out;
-    }
-    
-    if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) ) {
-        xcio_error(ioctxt, "Could not mlock region_mfn");
-        goto out;
-    }
-
-    /* Set the domain's name to that from the restore file */
-    if ( xc_domain_setname( xc_handle, dom, name ) ) {
-        xcio_error(ioctxt, "Could not set domain name");
-        goto out;
-    }
-
-    /* Set the domain's initial memory allocation 
-       to that from the restore file */
-
-    if ( xc_domain_setinitialmem(xc_handle, dom, 
-                                 nr_pfns * (PAGE_SIZE / 1024)) )
-    {
-        xcio_error(ioctxt, "Could not set domain initial memory");
-        goto out;
-    }
-
-    /* Get the domain's shared-info frame. */
-    op.cmd = DOM0_GETDOMAININFO;
-    op.u.getdomaininfo.domain = (domid_t)dom;
-    op.u.getdomaininfo.ctxt = NULL;
-    if ( do_dom0_op(xc_handle, &op) < 0 ) {
-        xcio_error(ioctxt, "Could not get information on new domain");
-        goto out;
-    }
-    shared_info_frame = op.u.getdomaininfo.shared_info_frame;
-
-    if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 )
-        goto out;
-
-
-
-    /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
-    if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) {
-        xcio_error(ioctxt, "Did not read correct number of frame numbers for new dom");
-        goto out;
-    }
-
-    if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) {
-        xcio_error(ioctxt, "Could not initialise for MMU updates");
-        goto out;
-    }
-
-    xcio_info(ioctxt, "Reloading memory pages:   0%%");
-
-    /*
-     * Now simply read each saved frame into its new machine frame.
-     * We uncanonicalise page tables as we go.
-     */
-    prev_pc = 0;
-
-    n=0;
-    while(1) {
-        int j;
-        unsigned long region_pfn_type[MAX_BATCH_SIZE];
-
-        this_pc = (n * 100) / nr_pfns;
-        if ( (this_pc - prev_pc) >= 5 ) {
-            xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc);
-            prev_pc = this_pc;
-        }
-
-        if ( xcio_read(ioctxt, &j, sizeof(int)) ) {
-            xcio_error(ioctxt, "Error when reading from state file");
-            goto out;
-        }
-
-        DPRINTF("batch %d\n",j);
-        if ( j == -1 ) {
-            verify = 1;
-            printf("Entering page verify mode\n");
-            continue;
-        }
-
-        if ( j == 0 ) break;  /* our work here is done */
-
-        if( j > MAX_BATCH_SIZE ) {
-            xcio_error(ioctxt, "Max batch size exceeded. Giving up.");
-            goto out;
-        }
-        if ( xcio_read(ioctxt, region_pfn_type, j*sizeof(unsigned long)) ) {
-            xcio_error(ioctxt, "Error when reading from state file");
-            goto out;
-        }
-
-        for(i=0; i<j; i++) {
-            if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) {
-                region_mfn[i] = 0; /* we know map will fail, but don't care */
-            } else {  
-                pfn = region_pfn_type[i] & ~LTAB_MASK;
-                region_mfn[i] = pfn_to_mfn_table[pfn];
-            }          
-        }
-        if ( (region_base = mfn_mapper_map_batch( xc_handle, dom, 
-                                                  PROT_WRITE,
-                                                  region_mfn,
-                                                  j )) == 0) {
-            xcio_error(ioctxt, "map batch failed");
-            goto out;
-        }
-
-        for(i=0;i<j;i++) {
-            unsigned long *ppage;
-
-            pfn = region_pfn_type[i] & ~LTAB_MASK;
-
-            if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) continue;
-
-            if (pfn>nr_pfns) {
-                xcio_error(ioctxt, "pfn out of range");
-                goto out;
-            }
-
-            region_pfn_type[i] &= LTAB_MASK;
-
-            pfn_type[pfn] = region_pfn_type[i];
-
-            mfn = pfn_to_mfn_table[pfn];
-
-            if ( verify ) {
-                ppage = (unsigned long*) buf;  /* debug case */
-            } else {
-                ppage = (unsigned long*) (region_base + i*PAGE_SIZE);
-            }
-
-            if ( xcio_read(ioctxt, ppage, PAGE_SIZE) ) {
-                xcio_error(ioctxt, "Error when reading from state file");
-                goto out;
-            }
-
-            switch( region_pfn_type[i] ) {
-            case 0:
-                break;
-
-            case L1TAB:
-            {
-                for ( k = 0; k < 1024; k++ ) {
-                    if ( ppage[k] & _PAGE_PRESENT ) {
-                        xpfn = ppage[k] >> PAGE_SHIFT;
-
-                        if ( xpfn >= nr_pfns ) {
-                            xcio_error(ioctxt, "Frame number in type %lu page table is "
-                                  "out of range. i=%d k=%d pfn=0x%lx "
-                                  "nr_pfns=%lu", region_pfn_type[i]>>28, i, 
-                                  k, xpfn, nr_pfns);
-                            goto out;
-                        }
-
-                        ppage[k] &= (PAGE_SIZE - 1) & 
-                            ~(_PAGE_GLOBAL | _PAGE_PAT);
-                        ppage[k] |= pfn_to_mfn_table[xpfn] << PAGE_SHIFT;
-                    }
-                }
-            }
-            break;
-
-            case L2TAB:
-            {
-                for ( k = 0; 
-                      k < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); 
-                      k++ ) {
-                    if ( ppage[k] & _PAGE_PRESENT ) {
-                        xpfn = ppage[k] >> PAGE_SHIFT;
-
-                        if ( xpfn >= nr_pfns ) {
-                            xcio_error(ioctxt, "Frame number in type %lu page table is "
-                                  "out of range. i=%d k=%d pfn=%lu nr_pfns=%lu",
-                                  region_pfn_type[i]>>28, i, k, xpfn, nr_pfns);
-
-                            goto out;
-                        }
-
-                        ppage[k] &= (PAGE_SIZE - 1) & 
-                            ~(_PAGE_GLOBAL | _PAGE_PSE);
-                        ppage[k] |= pfn_to_mfn_table[xpfn] << PAGE_SHIFT;
-                    }
-                }
-            }
-            break;
-
-            default:
-                xcio_error(ioctxt, "Bogus page type %lx page table is out of range."
-                      " i=%d nr_pfns=%lu", region_pfn_type[i], i, nr_pfns);
-                goto out;
-
-            } /* end of page type switch statement */
-
-            if ( verify ) {
-                int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE );
-                if (res) {
-                    int v;
-                    printf("************** pfn=%lx type=%lx gotcs=%08lx "
-                           "actualcs=%08lx\n", pfn, pfn_type[pfn], 
-                           csum_page(region_base + i*PAGE_SIZE), 
-                           csum_page(buf));
-                    for ( v = 0; v < 4; v++ ) {
-                        unsigned long *p = (unsigned long *)
-                            (region_base + i*PAGE_SIZE);
-                        if ( buf[v] != p[v] )
-                            printf("    %d: %08lx %08lx\n",
-                                   v, buf[v], p[v] );
-                    }
-                }
-            }
-
-            if ( add_mmu_update(xc_handle, mmu,
-                                (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, pfn) ) {
-                printf("machpys mfn=%ld pfn=%ld\n",mfn,pfn);
-                goto out;
-            }
-
-        } /* end of 'batch' for loop */
-
-        munmap( region_base, j*PAGE_SIZE );
-        n+=j; /* crude stats */
-    }
-
-    printf("Received all pages\n");
-
-    DPRINTF("Received all pages\n");
-
-    /*
-     * Pin page tables. Do this after writing to them as otherwise Xen
-     * will barf when doing the type-checking.
-     */
-    for ( i = 0; i < nr_pfns; i++ ) {
-        if ( pfn_type[i] == L1TAB ) {
-            if ( add_mmu_update(xc_handle, mmu,
-                                (pfn_to_mfn_table[i]<<PAGE_SHIFT) | 
-                                MMU_EXTENDED_COMMAND,
-                                MMUEXT_PIN_L1_TABLE) ) {
-                printf("ERR pin L1 pfn=%lx mfn=%lx\n",
-                       (unsigned long)i, pfn_to_mfn_table[i]);
-                goto out;
-            }
-        } else if ( pfn_type[i] == L2TAB ) {
-            if ( add_mmu_update(xc_handle, mmu,
-                                (pfn_to_mfn_table[i]<<PAGE_SHIFT) | 
-                                MMU_EXTENDED_COMMAND,
-                                MMUEXT_PIN_L2_TABLE) ) {
-                printf("ERR pin L2 pfn=%lx mfn=%lx\n",
-                       (unsigned long)i, pfn_to_mfn_table[i]);
-                goto out;
-            }
-        }
-    }
-
-    if ( finish_mmu_updates(xc_handle, mmu) ) goto out;
-
-    xcio_info(ioctxt, "\b\b\b\b100%%\nMemory reloaded.\n");
-
-
-    if ( xcio_read(ioctxt, &ctxt,                 sizeof(ctxt)) ||
-         xcio_read(ioctxt, shared_info,           PAGE_SIZE) ) {
-        xcio_error(ioctxt, "Error when reading from state file");
-        goto out;
-    }
-
-    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
-    pfn = ctxt.cpu_ctxt.esi;
-    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) )
-    {
-        xcio_error(ioctxt, "Suspend record frame number is bad");
-        goto out;
-    }
-    ctxt.cpu_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
-    p_srec = map_pfn_writeable(pm_handle, mfn);
-    p_srec->resume_info.nr_pages    = nr_pfns;
-    p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
-    p_srec->resume_info.flags       = 0;
-    unmap_pfn(pm_handle, p_srec);
-
-    /* Uncanonicalise each GDT frame number. */
-    if ( ctxt.gdt_ents > 8192 ) {
-        xcio_error(ioctxt, "GDT entry count out of range");
-        goto out;
-    }
-    for ( i = 0; i < ctxt.gdt_ents; i += 512 ) {
-        pfn = ctxt.gdt_frames[i];
-        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) {
-            xcio_error(ioctxt, "GDT frame number is bad");
-            goto out;
-        }
-        ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn];
-    }
-
-    /* Uncanonicalise the page table base pointer. */
-    pfn = ctxt.pt_base >> PAGE_SHIFT;
-    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) {
-        printf("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx\n",
-               pfn, nr_pfns, pfn_type[pfn], (unsigned long)L2TAB);
-        xcio_error(ioctxt, "PT base is bad.");
-        goto out;
-    }
-    ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
-
-
-    /* clear any pending events and the selector */
-    memset( &(((shared_info_t *)shared_info)->evtchn_pending[0]),
-            0, sizeof (((shared_info_t *)shared_info)->evtchn_pending)+
-            sizeof(((shared_info_t *)shared_info)->evtchn_pending_sel) );
-
-    /* Copy saved contents of shared-info page. No checking needed. */
-    ppage = map_pfn_writeable(pm_handle, shared_info_frame);
-    memcpy(ppage, shared_info, sizeof(shared_info_t));
-    unmap_pfn(pm_handle, ppage);
-
-
-    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
-    for ( i = 0; i < (nr_pfns+1023)/1024; i++ ) {
-        unsigned long pfn, mfn;
-
-        pfn = pfn_to_mfn_frame_list[i];
-        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) {
-            xcio_error(ioctxt, "PFN-to-MFN frame number is bad");
-            goto out;
-        }
-        mfn = pfn_to_mfn_table[pfn];
-        pfn_to_mfn_frame_list[i] = mfn;
-    }
-    
-    if ( (live_pfn_to_mfn_table = 
-          mfn_mapper_map_batch(xc_handle, dom, 
-                               PROT_WRITE,
-                               pfn_to_mfn_frame_list,
-                               (nr_pfns+1023)/1024 )) == 0 ) {
-        xcio_error(ioctxt, "Couldn't map pfn_to_mfn table");
-        goto out;
-    }
-
-    memcpy( live_pfn_to_mfn_table, pfn_to_mfn_table, 
-            nr_pfns*sizeof(unsigned long) );
-
-    munmap( live_pfn_to_mfn_table, ((nr_pfns+1023)/1024)*PAGE_SIZE );
-
-    /*
-     * Safety checking of saved context:
-     *  1. cpu_ctxt is fine, as Xen checks that on context switch.
-     *  2. fpu_ctxt is fine, as it can't hurt Xen.
-     *  3. trap_ctxt needs the code selectors checked.
-     *  4. fast_trap_idx is checked by Xen.
-     *  5. ldt base must be page-aligned, no more than 8192 ents, ...
-     *  6. gdt already done, and further checking is done by Xen.
-     *  7. check that guestos_ss is safe.
-     *  8. pt_base is already done.
-     *  9. debugregs are checked by Xen.
-     *  10. callback code selectors need checking.
-     */
-    for ( i = 0; i < 256; i++ ) {
-        ctxt.trap_ctxt[i].vector = i;
-        if ( (ctxt.trap_ctxt[i].cs & 3) == 0 )
-            ctxt.trap_ctxt[i].cs = FLAT_GUESTOS_CS;
-    }
-    if ( (ctxt.guestos_ss & 3) == 0 ){
-        ctxt.guestos_ss = FLAT_GUESTOS_DS;
-    }
-    if ( (ctxt.event_callback_cs & 3) == 0 ){
-        ctxt.event_callback_cs = FLAT_GUESTOS_CS;
-    }
-    if ( (ctxt.failsafe_callback_cs & 3) == 0 ){
-        ctxt.failsafe_callback_cs = FLAT_GUESTOS_CS;
-    }
-    if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
-         (ctxt.ldt_ents > 8192) ||
-         (ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
-         ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) )
-    {
-        xcio_error(ioctxt, "Bad LDT base or size");
-        goto out;
-    }
-   
-    op.cmd = DOM0_BUILDDOMAIN;
-    op.u.builddomain.domain   = (domid_t)dom;
-    op.u.builddomain.ctxt = &ctxt;
-    rc = do_dom0_op(xc_handle, &op);
-
-    /* don't start the domain as we have console etc to set up */
-  
-    if( rc == 0 ) {
-        /* Success: print the domain id. */
-        xcio_info(ioctxt, "DOM=%lu\n", dom);
-        return 0;
-    }
-
-
- out:
-    if ( (rc != 0) && (dom != 0) ){
-        xc_domain_destroy(xc_handle, dom);
-    }
-    if ( mmu != NULL ){
-        free(mmu);
-    }
-    if ( pm_handle >= 0 ){
-        (void)close_pfn_mapper(pm_handle);
-    }
-    if ( pfn_to_mfn_table != NULL ){
-        free(pfn_to_mfn_table);
-    }
-    if ( pfn_type != NULL ){
-        free(pfn_type);
-    }
-
-    if ( rc == 0 ){
-        ioctxt->domain = dom;
-    }
-    DPRINTF("Restore exit with rc=%d\n",rc);
-    return rc;
-}
diff --git a/tools/xc/lib/xc_linux_save.c b/tools/xc/lib/xc_linux_save.c
deleted file mode 100644 (file)
index 44ffb6b..0000000
+++ /dev/null
@@ -1,840 +0,0 @@
-/******************************************************************************
- * xc_linux_save.c
- * 
- * Save the state of a running Linux session.
- * 
- * Copyright (c) 2003, K A Fraser.
- */
-
-#include <sys/time.h>
-#include "xc_private.h"
-#include <asm-xen/suspend.h>
-
-#define BATCH_SIZE 1024   /* 1024 pages (4MB) at a time */
-
-#define DEBUG 0
-#define DDEBUG 0
-
-#if DEBUG
-#define DPRINTF(_f, _a...) printf ( _f , ## _a )
-#else
-#define DPRINTF(_f, _a...) ((void)0)
-#endif
-
-#if DDEBUG
-#define DDPRINTF(_f, _a...) printf ( _f , ## _a )
-#else
-#define DDPRINTF(_f, _a...) ((void)0)
-#endif
-
-/*
- * Returns TRUE if the given machine frame number has a unique mapping
- * in the guest's pseudophysical map.
- * 0x80000000-3 mark the shared_info, and blk/net rings
- */
-#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn)                                    \
-    (((_mfn) < (1024*1024)) &&                                            \
-     (((live_mfn_to_pfn_table[_mfn] < nr_pfns) &&                         \
-       (live_pfn_to_mfn_table[live_mfn_to_pfn_table[_mfn]] == (_mfn))) || \
-      ((live_mfn_to_pfn_table[_mfn] >= 0x80000000) &&                     \
-       (live_mfn_to_pfn_table[_mfn] <= 0x80000003)) ||                    \
-      (live_pfn_to_mfn_table[live_mfn_to_pfn_table[_mfn]] == 0x80000004)))
-     
-/* Returns TRUE if MFN is successfully converted to a PFN. */
-#define translate_mfn_to_pfn(_pmfn)            \
-({                                             \
-    unsigned long mfn = *(_pmfn);              \
-    int _res = 1;                              \
-    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )      \
-        _res = 0;                              \
-    else                                       \
-        *(_pmfn) = live_mfn_to_pfn_table[mfn]; \
-    _res;                                      \
-})
-
-static inline int test_bit ( int nr, volatile void * addr)
-{
-    return (((unsigned long*)addr)[nr/(sizeof(unsigned long)*8)] >> 
-            (nr % (sizeof(unsigned long)*8))) & 1;
-}
-
-static inline void clear_bit ( int nr, volatile void * addr)
-{
-    ((unsigned long*)addr)[nr/(sizeof(unsigned long)*8)] &= 
-        ~(1 << (nr % (sizeof(unsigned long)*8) ) );
-}
-
-static inline void set_bit ( int nr, volatile void * addr)
-{
-    ((unsigned long*)addr)[nr/(sizeof(unsigned long)*8)] |= 
-        (1 << (nr % (sizeof(unsigned long)*8) ) );
-}
-
-/* Returns the hamming weight (i.e. the number of bits set) in a N-bit word */
-static inline unsigned int hweight32(unsigned int w)
-{
-    unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
-    res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
-    res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
-    res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
-    return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
-}
-
-static inline int count_bits ( int nr, volatile void *addr)
-{
-    int i, count = 0;
-    unsigned long *p = (unsigned long *)addr;
-    /* We know that the array is padded to unsigned long. */
-    for(i=0;i<nr/(sizeof(unsigned long)*8);i++,p++)
-        count += hweight32( *p );
-    return count;
-}
-
-static inline int permute( int i, int nr, int order_nr  )
-{
-    /* Need a simple permutation function so that we scan pages in a
-       pseudo random order, enabling us to get a better estimate of
-       the domain's page dirtying rate as we go (there are often 
-       contiguous ranges of pfns that have similar behaviour, and we
-       want to mix them up. */
-
-    /* e.g. nr->oder 15->4 16->4 17->5 */
-    /* 512MB domain, 128k pages, order 17 */
-
-    /*
-      QPONMLKJIHGFEDCBA  
-             QPONMLKJIH  
-      GFEDCBA  
-     */
-    
-    /*
-      QPONMLKJIHGFEDCBA  
-                  EDCBA  
-             QPONM
-      LKJIHGF
-      */
-
-    do { i = ((i>>(order_nr-10)) | ( i<<10 ) ) & ((1<<order_nr)-1); }
-    while ( i >= nr ); /* this won't ever loop if nr is a power of 2 */
-
-    return i;
-}
-
-static long long tv_to_us( struct timeval *new )
-{
-    return (new->tv_sec * 1000000) + new->tv_usec;
-}
-
-static long long llgettimeofday()
-{
-    struct timeval now;
-    gettimeofday(&now, NULL);
-    return tv_to_us(&now);
-}
-
-static long long tv_delta( struct timeval *new, struct timeval *old )
-{
-    return ((new->tv_sec - old->tv_sec)*1000000 ) + 
-        (new->tv_usec - old->tv_usec);
-}
-
-static int print_stats( int xc_handle, u32 domid, 
-                        int pages_sent, xc_shadow_control_stats_t *stats,
-                        int print )
-{
-    static struct timeval wall_last;
-    static long long      d0_cpu_last;
-    static long long      d1_cpu_last;
-
-    struct timeval        wall_now;
-    long long             wall_delta;
-    long long             d0_cpu_now, d0_cpu_delta;
-    long long             d1_cpu_now, d1_cpu_delta;
-
-    gettimeofday(&wall_now, NULL);
-
-    d0_cpu_now = xc_domain_get_cpu_usage( xc_handle, 0 )/1000;
-    d1_cpu_now = xc_domain_get_cpu_usage( xc_handle, domid )/1000;
-
-    if ( (d0_cpu_now == -1) || (d1_cpu_now == -1) ) 
-        printf("ARRHHH!!\n");
-
-    wall_delta = tv_delta(&wall_now,&wall_last)/1000;
-
-    if ( wall_delta == 0 ) wall_delta = 1;
-
-    d0_cpu_delta  = (d0_cpu_now - d0_cpu_last)/1000;
-    d1_cpu_delta  = (d1_cpu_now - d1_cpu_last)/1000;
-
-    if ( print )
-        printf("delta %lldms, dom0 %d%%, target %d%%, sent %dMb/s, "
-               "dirtied %dMb/s\n",
-               wall_delta, 
-               (int)((d0_cpu_delta*100)/wall_delta),
-               (int)((d1_cpu_delta*100)/wall_delta),
-               (int)((pages_sent*PAGE_SIZE*8)/(wall_delta*1000)),
-               (int)((stats->dirty_count*PAGE_SIZE*8)/(wall_delta*1000)));
-
-    d0_cpu_last  = d0_cpu_now;
-    d1_cpu_last  = d1_cpu_now;
-    wall_last = wall_now; 
-
-    return 0;
-}
-
-/** Write the vmconfig string.
- * It is stored as a 4-byte count 'n' followed by n bytes.
- *
- * @param ioctxt i/o context
- * @return 0 on success, non-zero on error.
- */
-static int write_vmconfig(XcIOContext *ioctxt){
-    int err = -1;
-    if(xcio_write(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))) goto exit;
-    if(xcio_write(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)) goto exit;
-    err = 0;
-  exit:
-    return err;
-}
-
-static int analysis_phase( int xc_handle, u32 domid, 
-                           int nr_pfns, unsigned long *arr )
-{
-    long long start, now;
-    xc_shadow_control_stats_t stats;
-
-    start = llgettimeofday();
-
-    while ( 0 )
-    {
-        int i;
-
-        xc_shadow_control( xc_handle, domid, 
-                           DOM0_SHADOW_CONTROL_OP_CLEAN2,
-                           arr, nr_pfns, NULL);
-        printf("#Flush\n");
-        for ( i = 0; i < 100; i++ )
-        {     
-            usleep(10000);     
-            now = llgettimeofday();
-            xc_shadow_control( xc_handle, domid, 
-                               DOM0_SHADOW_CONTROL_OP_PEEK,
-                               NULL, 0, &stats);
-
-            printf("now= %lld faults= %ld dirty= %ld dirty_net= %ld "
-                   "dirty_block= %ld\n", 
-                   ((now-start)+500)/1000, 
-                   stats.fault_count, stats.dirty_count,
-                   stats.dirty_net_count, stats.dirty_block_count);
-        }
-    }
-
-    return -1;
-}
-
-int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
-{
-    dom0_op_t op;
-    int rc = 1, i, j, k, last_iter, iter = 0;
-    unsigned long mfn;
-    u32 domid = ioctxt->domain;
-    int live = (ioctxt->flags & XCFLAGS_LIVE);
-    int debug = (ioctxt->flags & XCFLAGS_DEBUG);
-    int sent_last_iter, skip_this_iter;
-
-    /* Important tuning parameters */
-    int max_iters  = 29; /* limit us to 30 times round loop */
-    int max_factor = 3;  /* never send more than 3x nr_pfns */
-
-    /* The new domain's shared-info frame number. */
-    unsigned long shared_info_frame;
-    
-    /* A copy of the CPU context of the guest. */
-    full_execution_context_t ctxt;
-
-    /* A copy of the domain's name. */
-    char name[MAX_DOMAIN_NAME];
-
-    /* A table containg the type of each PFN (/not/ MFN!). */
-    unsigned long *pfn_type = NULL;
-    unsigned long *pfn_batch = NULL;
-
-    /* A temporary mapping, and a copy, of one frame of guest memory. */
-    unsigned long page[1024];
-
-    /* A copy of the pfn-to-mfn table frame list. */
-    unsigned long *live_pfn_to_mfn_frame_list;
-    unsigned long pfn_to_mfn_frame_list[1024];
-
-    /* Live mapping of the table mapping each PFN to its current MFN. */
-    unsigned long *live_pfn_to_mfn_table = NULL;
-    /* Live mapping of system MFN to PFN table. */
-    unsigned long *live_mfn_to_pfn_table = NULL;
-    
-    /* Live mapping of shared info structure */
-    unsigned long *live_shinfo;
-
-    /* base of the region in which domain memory is mapped */
-    unsigned char *region_base = NULL;
-
-    /* A temporary mapping, and a copy, of the guest's suspend record. */
-    suspend_record_t *p_srec;
-
-    /* number of pages we're dealing with */
-    unsigned long nr_pfns;
-
-    /* power of 2 order of nr_pfns */
-    int order_nr; 
-
-    /* bitmap of pages:
-       - that should be sent this iteration (unless later marked as skip); 
-       - to skip this iteration because already dirty;
-       - to fixup by sending at the end if not already resent; */
-    unsigned long *to_send, *to_skip, *to_fix;
-    
-    xc_shadow_control_stats_t stats;
-
-    int needed_to_fix = 0;
-    int total_sent    = 0;
-    
-    if (mlock(&ctxt, sizeof(ctxt))) {
-        xcio_perror(ioctxt, "Unable to mlock ctxt");
-        return 1;
-    }
-
-    /* Ensure that the domain exists, and that it is stopped. */
-    if ( xc_domain_pause(xc_handle, domid) ){
-        xcio_perror(ioctxt, "Could not pause domain");
-        goto out;
-    }
-
-    if ( xc_domain_getfullinfo( xc_handle, domid, &op, &ctxt) )
-    {
-        PERROR("Could not get full domain info");
-        goto out;
-    }
-    memcpy(name, op.u.getdomaininfo.name, sizeof(name));
-    shared_info_frame = op.u.getdomaininfo.shared_info_frame;
-
-    /* A cheesy test to see whether the domain contains valid state. */
-    if ( ctxt.pt_base == 0 ){
-        xcio_error(ioctxt, "Domain is not in a valid Linux guest OS state");
-        goto out;
-    }
-
-    /* Map the suspend-record MFN to pin it. The page must be owned by 
-       domid for this to succeed. */
-    p_srec = mfn_mapper_map_single(xc_handle, domid,
-                                   sizeof(*p_srec), PROT_READ, 
-                                   ctxt.cpu_ctxt.esi);
-    if (!p_srec){
-        xcio_error(ioctxt, "Couldn't map state record");
-        goto out;
-    }
-
-    nr_pfns = p_srec->nr_pfns;
-
-    /* cheesy sanity check */
-    if ( nr_pfns > 1024*1024 ){
-        xcio_error(ioctxt, "Invalid state record -- pfn count out of range");
-        goto out;
-    }
-
-    /* the pfn_to_mfn_frame_list fits in a single page */
-    live_pfn_to_mfn_frame_list = 
-        mfn_mapper_map_single(xc_handle, domid, 
-                              PAGE_SIZE, PROT_READ, 
-                              p_srec->pfn_to_mfn_frame_list );
-
-    if (!live_pfn_to_mfn_frame_list){
-        xcio_error(ioctxt, "Couldn't map pfn_to_mfn_frame_list");
-        goto out;
-    }
-
-    /* Track the mfn_to_pfn table down from the domains PT */
-    {
-        unsigned long *pgd;
-        unsigned long mfn_to_pfn_table_start_mfn;
-
-        pgd = mfn_mapper_map_single(xc_handle, domid, 
-                                    PAGE_SIZE, PROT_READ, 
-                                    ctxt.pt_base>>PAGE_SHIFT);
-
-        mfn_to_pfn_table_start_mfn = 
-            pgd[HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT]>>PAGE_SHIFT;
-
-        live_mfn_to_pfn_table = 
-            mfn_mapper_map_single(xc_handle, ~0UL, 
-                                  PAGE_SIZE*1024, PROT_READ, 
-                                  mfn_to_pfn_table_start_mfn );
-    }
-
-    /* Map all the frames of the pfn->mfn table. For migrate to succeed, 
-       the guest must not change which frames are used for this purpose. 
-       (its not clear why it would want to change them, and we'll be OK
-       from a safety POV anyhow. */
-
-    live_pfn_to_mfn_table = mfn_mapper_map_batch(xc_handle, domid, 
-                                                 PROT_READ,
-                                                 live_pfn_to_mfn_frame_list,
-                                                 (nr_pfns+1023)/1024 );  
-    if( !live_pfn_to_mfn_table ){
-        xcio_perror(ioctxt, "Couldn't map pfn_to_mfn table");
-        goto out;
-    }
-
-
-    /* Canonicalise the pfn-to-mfn table frame-number list. */
-    memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE );
-    for ( i = 0; i < nr_pfns; i += 1024 ){
-        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) ){
-            xcio_error(ioctxt, "Frame # in pfn-to-mfn frame list is not in pseudophys");
-            goto out;
-        }
-    }
-
-    /* At this point, we can start the domain again if we're doing a
-       live suspend */
-
-    if( live ){ 
-        if ( xc_shadow_control( xc_handle, domid, 
-                                DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY,
-                                NULL, 0, NULL ) < 0 ) {
-            xcio_error(ioctxt, "Couldn't enable shadow mode");
-            goto out;
-        }
-
-        if ( xc_domain_unpause(xc_handle, domid) < 0 ){
-            xcio_error(ioctxt, "Couldn't unpause domain");
-            goto out;
-        }
-
-        last_iter = 0;
-        sent_last_iter = 1<<20; /* 4GB of pages */
-    } else{
-        last_iter = 1;
-    }
-
-    /* calculate the power of 2 order of nr_pfns, e.g.
-       15->4 16->4 17->5 */
-    for( i=nr_pfns-1, order_nr=0; i ; i>>=1, order_nr++ );
-
-    /* Setup to_send bitmap */
-    {
-        int sz = (nr_pfns/8) + 8; /* includes slop at end of array */
-        to_send = malloc( sz );
-        to_fix  = calloc( 1, sz );
-        to_skip = malloc( sz );
-
-        if (!to_send || !to_fix || !to_skip){
-            xcio_error(ioctxt, "Couldn't allocate to_send array");
-            goto out;
-        }
-
-        memset( to_send, 0xff, sz );
-
-        if ( mlock( to_send, sz ) ){
-            xcio_perror(ioctxt, "Unable to mlock to_send");
-            return 1;
-        }
-
-        /* (to fix is local only) */
-
-        if ( mlock( to_skip, sz ) ){
-            xcio_perror(ioctxt, "Unable to mlock to_skip");
-            return 1;
-        }
-
-    }
-
-    analysis_phase( xc_handle, domid, nr_pfns, to_skip );
-
-    /* We want zeroed memory so use calloc rather than malloc. */
-    pfn_type = calloc(BATCH_SIZE, sizeof(unsigned long));
-    pfn_batch = calloc(BATCH_SIZE, sizeof(unsigned long));
-
-    if ( (pfn_type == NULL) || (pfn_batch == NULL) ){
-        errno = ENOMEM;
-        goto out;
-    }
-
-    if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) ){
-        xcio_error(ioctxt, "Unable to mlock");
-        goto out;
-    }
-
-
-    /*
-     * Quick belt and braces sanity check.
-     */
-#if DEBUG
-    for ( i = 0; i < nr_pfns; i++ ){
-        mfn = live_pfn_to_mfn_table[i];
-
-        if( (live_mfn_to_pfn_table[mfn] != i) && (mfn != 0x80000004) )
-            printf("i=0x%x mfn=%x live_mfn_to_pfn_table=%x\n",
-                   i,mfn,live_mfn_to_pfn_table[mfn]);
-    }
-#endif
-
-    /* Map the shared info frame */
-    live_shinfo = mfn_mapper_map_single(xc_handle, domid,
-                                        PAGE_SIZE, PROT_READ,
-                                        shared_info_frame);
-
-    if (!live_shinfo){
-        xcio_error(ioctxt, "Couldn't map live_shinfo");
-        goto out;
-    }
-
-    /* Start writing out the saved-domain record. */
-
-    if ( xcio_write(ioctxt, "LinuxGuestRecord",    16) ||
-         xcio_write(ioctxt, name,                  sizeof(name)) ||
-         xcio_write(ioctxt, &nr_pfns,              sizeof(unsigned long)) ||
-         xcio_write(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ){
-        xcio_error(ioctxt, "Error writing header");
-        goto out;
-    }
-    if(write_vmconfig(ioctxt)){
-        xcio_error(ioctxt, "Error writing vmconfig");
-        goto out;
-    }
-
-    print_stats( xc_handle, domid, 0, &stats, 0 );
-
-    /* Now write out each data page, canonicalising page tables as we go... */
-    
-    while(1){
-        unsigned int prev_pc, sent_this_iter, N, batch;
-
-        iter++;
-        sent_this_iter = 0;
-        skip_this_iter = 0;
-        prev_pc = 0;
-        N=0;
-
-        xcio_info(ioctxt, "Saving memory pages: iter %d   0%%", iter);
-
-        while( N < nr_pfns ){
-            unsigned int this_pc = (N * 100) / nr_pfns;
-
-            if ( (this_pc - prev_pc) >= 5 ){
-                xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc);
-                prev_pc = this_pc;
-            }
-
-            /* slightly wasteful to peek the whole array evey time, 
-               but this is fast enough for the moment. */
-
-            if ( !last_iter && 
-                 xc_shadow_control(xc_handle, domid, 
-                                   DOM0_SHADOW_CONTROL_OP_PEEK,
-                                   to_skip, nr_pfns, NULL) != nr_pfns ) {
-                xcio_error(ioctxt, "Error peeking shadow bitmap");
-                goto out;
-            }
-     
-
-            /* load pfn_type[] with the mfn of all the pages we're doing in
-               this batch. */
-
-            for ( batch = 0; batch < BATCH_SIZE && N < nr_pfns ; N++ )
-            {
-                int n = permute(N, nr_pfns, order_nr );
-
-                if ( 0 && debug ) {
-                    fprintf(stderr,"%d pfn= %08lx mfn= %08lx %d  "
-                            " [mfn]= %08lx\n",
-                            iter, (unsigned long)n, live_pfn_to_mfn_table[n],
-                            test_bit(n,to_send),
-                            live_mfn_to_pfn_table[live_pfn_to_mfn_table[n]&
-                                                 0xFFFFF]);
-                }
-
-                if ( !last_iter && 
-                     test_bit(n, to_send) && 
-                     test_bit(n, to_skip) ) {
-                    skip_this_iter++; /* stats keeping */
-                }
-
-                if ( !((test_bit(n, to_send) && !test_bit(n, to_skip)) ||
-                       (test_bit(n, to_send) && last_iter) ||
-                       (test_bit(n, to_fix)  && last_iter)) ) {
-                    continue;
-                }
-
-                /* we get here if:
-                   1. page is marked to_send & hasn't already been re-dirtied
-                   2. (ignore to_skip in last iteration)
-                   3. add in pages that still need fixup (net bufs)
-                */
-  
-                pfn_batch[batch] = n;
-                pfn_type[batch] = live_pfn_to_mfn_table[n];
-
-                if( pfn_type[batch] == 0x80000004 ){
-                    /* not currently in pusedo-physical map -- set bit
-                       in to_fix that we must send this page in last_iter
-                       unless its sent sooner anyhow */
-
-                    set_bit( n, to_fix );
-                    if( iter>1 )
-                        DDPRINTF("netbuf race: iter %d, pfn %lx. mfn %lx\n",
-                                 iter,n,pfn_type[batch]);
-                    continue;
-                }
-
-                if ( last_iter && 
-                     test_bit(n, to_fix) && 
-                     !test_bit(n, to_send) )
-                {
-                    needed_to_fix++;
-                    DPRINTF("Fix! iter %d, pfn %lx. mfn %lx\n",
-                            iter,n,pfn_type[batch]);
-                }
-
-                clear_bit(n, to_fix); 
-
-                batch++;
-            }
-     
-            DDPRINTF("batch %d:%d (n=%d)\n", iter, batch, n);
-
-            if ( batch == 0 )
-                goto skip; /* vanishingly unlikely... */
-      
-            if ( (region_base = mfn_mapper_map_batch(xc_handle, domid, 
-                                                     PROT_READ,
-                                                     pfn_type,
-                                                     batch)) == 0 ){
-                xcio_perror(ioctxt, "map batch failed");
-                goto out;
-            }
-     
-            if ( get_pfn_type_batch(xc_handle, domid, batch, pfn_type) ){
-                xcio_error(ioctxt, "get_pfn_type_batch failed");
-                goto out;
-            }
-     
-            for ( j = 0; j < batch; j++ ){
-                if ( (pfn_type[j] & LTAB_MASK) == XTAB ){
-                    DDPRINTF("type fail: page %i mfn %08lx\n",j,pfn_type[j]);
-                    continue;
-                }
-  
-                if ( 0 && debug )
-                    fprintf(stderr, "%d pfn= %08lx mfn= %08lx [mfn]= %08lx"
-                            " sum= %08lx\n",
-                            iter, 
-                            (pfn_type[j] & LTAB_MASK) | pfn_batch[j],
-                            pfn_type[j],
-                            live_mfn_to_pfn_table[pfn_type[j]&(~LTAB_MASK)],
-                            csum_page(region_base + (PAGE_SIZE*j)));
-
-                /* canonicalise mfn->pfn */
-                pfn_type[j] = (pfn_type[j] & LTAB_MASK) | pfn_batch[j];
-            }
-
-            if ( xcio_write(ioctxt, &batch, sizeof(int) ) ){
-                xcio_error(ioctxt, "Error when writing to state file (2)");
-                goto out;
-            }
-
-            if ( xcio_write(ioctxt, pfn_type, sizeof(unsigned long)*j ) ){
-                xcio_error(ioctxt, "Error when writing to state file (3)");
-                goto out;
-            }
-     
-            /* entering this loop, pfn_type is now in pfns (Not mfns) */
-            for( j = 0; j < batch; j++ ){
-                /* write out pages in batch */
-                if( (pfn_type[j] & LTAB_MASK) == XTAB){
-                    DDPRINTF("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]);
-                    continue;
-                }
-  
-                if ( ((pfn_type[j] & LTAB_MASK) == L1TAB) || 
-                     ((pfn_type[j] & LTAB_MASK) == L2TAB) ){
-                    memcpy(page, region_base + (PAGE_SIZE*j), PAGE_SIZE);
-      
-                    for ( k = 0; 
-                          k < (((pfn_type[j] & LTAB_MASK) == L2TAB) ? 
-                               (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) :
-                               1024); 
-                          k++ ){
-                        unsigned long pfn;
-
-                        if ( !(page[k] & _PAGE_PRESENT) )
-                            continue;
-                        
-                        mfn = page[k] >> PAGE_SHIFT;      
-                        pfn = live_mfn_to_pfn_table[mfn];
-
-                        if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
-                        {
-                            /* I don't think this should ever happen */
-                            printf("FNI %d : [%08lx,%d] pte=%08lx, "
-                                   "mfn=%08lx, pfn=%08lx [mfn]=%08lx\n",
-                                   j, pfn_type[j], k,
-                                   page[k], mfn, live_mfn_to_pfn_table[mfn],
-                                   (live_mfn_to_pfn_table[mfn]<nr_pfns)? 
-                                   live_pfn_to_mfn_table[
-                                       live_mfn_to_pfn_table[mfn]] : 
-                                   0xdeadbeef);
-
-                            pfn = 0; /* be suspicious */
-                        }
-
-                        page[k] &= PAGE_SIZE - 1;
-                        page[k] |= pfn << PAGE_SHIFT;
-   
-#if 0
-                        printf("L%d i=%d pfn=%d mfn=%d k=%d pte=%08lx "
-                               "xpfn=%d\n",
-                               pfn_type[j]>>28,
-                               j,i,mfn,k,page[k],page[k]>>PAGE_SHIFT);
-#endif     
-   
-                    } /* end of page table rewrite for loop */
-      
-                    if ( xcio_write(ioctxt, page, PAGE_SIZE) ){
-                        xcio_error(ioctxt, "Error when writing to state file (4)");
-                        goto out;
-                    }
-      
-                }  /* end of it's a PT page */ else {  /* normal page */
-
-                    if ( xcio_write(ioctxt, region_base + (PAGE_SIZE*j), 
-                                     PAGE_SIZE) ){
-                        xcio_error(ioctxt, "Error when writing to state file (5)");
-                        goto out;
-                    }
-                }
-            } /* end of the write out for this batch */
-     
-            sent_this_iter += batch;
-
-        } /* end of this while loop for this iteration */
-
-        munmap(region_base, batch*PAGE_SIZE);
-
-    skip: 
-
-        total_sent += sent_this_iter;
-
-        xcio_info(ioctxt, "\r %d: sent %d, skipped %d, ", 
-                       iter, sent_this_iter, skip_this_iter );
-
-        if ( last_iter ) {
-            print_stats( xc_handle, domid, sent_this_iter, &stats, 1);
-
-            xcio_info(ioctxt, "Total pages sent= %d (%.2fx)\n", 
-                           total_sent, ((float)total_sent)/nr_pfns );
-            xcio_info(ioctxt, "(of which %d were fixups)\n", needed_to_fix  );
-        }       
-
-        if (last_iter && debug){
-            int minusone = -1;
-            memset( to_send, 0xff, (nr_pfns+8)/8 );
-            debug = 0;
-            printf("Entering debug resend-all mode\n");
-    
-            /* send "-1" to put receiver into debug mode */
-            if ( xcio_write(ioctxt, &minusone, sizeof(int)) )
-            {
-                xcio_error(ioctxt, "Error when writing to state file (6)");
-                goto out;
-            }
-
-            continue;
-        }
-
-        if ( last_iter ) break;
-
-        if ( live )
-        {
-            if ( 
-                /* ( sent_this_iter > (sent_last_iter * 0.95) ) || */
-                (iter >= max_iters) || 
-                (sent_this_iter+skip_this_iter < 50) || 
-                (total_sent > nr_pfns*max_factor) )
-            {
-                DPRINTF("Start last iteration\n");
-                last_iter = 1;
-
-                xc_domain_pause( xc_handle, domid );
-            } 
-
-            if ( xc_shadow_control( xc_handle, domid, 
-                                    DOM0_SHADOW_CONTROL_OP_CLEAN2,
-                                    to_send, nr_pfns, &stats ) != nr_pfns ) 
-            {
-                xcio_error(ioctxt, "Error flushing shadow PT");
-                goto out;
-            }
-
-            sent_last_iter = sent_this_iter;
-
-            print_stats( xc_handle, domid, sent_this_iter, &stats, 1);
-     
-        }
-
-
-    } /* end of while 1 */
-
-    DPRINTF("All memory is saved\n");
-
-    /* Success! */
-    rc = 0;
-    
-    /* Zero terminate */
-    if ( xcio_write(ioctxt, &rc, sizeof(int)) )
-    {
-        xcio_error(ioctxt, "Error when writing to state file (6)");
-        goto out;
-    }
-
-    /* Get the final execution context */
-    if ( xc_domain_getfullinfo( xc_handle, domid, &op, &ctxt) )
-    {
-        xcio_perror(ioctxt, "Could not get full domain info");
-        goto out;
-    }
-
-    /* Canonicalise the suspend-record frame number. */
-    if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) ){
-        xcio_error(ioctxt, "State record is not in range of pseudophys map");
-        goto out;
-    }
-
-    /* Canonicalise each GDT frame number. */
-    for ( i = 0; i < ctxt.gdt_ents; i += 512 ) {
-        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) {
-            xcio_error(ioctxt, "GDT frame is not in range of pseudophys map");
-            goto out;
-        }
-    }
-
-    /* Canonicalise the page table base pointer. */
-    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) ) {
-        xcio_error(ioctxt, "PT base is not in range of pseudophys map");
-        goto out;
-    }
-    ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] <<
-        PAGE_SHIFT;
-
-    if ( xcio_write(ioctxt, &ctxt,       sizeof(ctxt)) ||
-         xcio_write(ioctxt, live_shinfo, PAGE_SIZE) ) {
-        xcio_error(ioctxt, "Error when writing to state file (1)");
-        goto out;
-    }
-    munmap(live_shinfo, PAGE_SIZE);
-
- out:
-    if ( pfn_type != NULL ) free(pfn_type);
-    DPRINTF("Save exit rc=%d\n",rc);
-    return !!rc;
-
-}
diff --git a/tools/xc/lib/xc_misc.c b/tools/xc/lib/xc_misc.c
deleted file mode 100644 (file)
index 0019ffe..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/******************************************************************************
- * xc_misc.c
- * 
- * Miscellaneous control interface functions.
- */
-
-#include "xc_private.h"
-
-int xc_interface_open(void)
-{
-    int fd = open("/proc/xen/privcmd", O_RDWR);
-    if ( fd == -1 )
-        PERROR("Could not obtain handle on privileged command interface");
-    return fd;
-}
-
-int xc_interface_close(int xc_handle)
-{
-    return close(xc_handle);
-}
-
-
-#define CONSOLE_RING_CLEAR 1
-
-int xc_readconsolering(int xc_handle,
-                       char *str, 
-                       unsigned int max_chars, 
-                       int clear)
-{
-    int ret;
-    dom0_op_t op;
-
-    op.cmd = DOM0_READCONSOLE;
-    op.u.readconsole.str = (unsigned long)str;
-    op.u.readconsole.count = max_chars;
-    op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0;
-
-    if ( (ret = mlock(str, max_chars)) != 0 )
-        return ret;
-
-    if ( (ret = do_dom0_op(xc_handle, &op)) >= 0 )
-        str[ret] = '\0';
-
-    (void)munlock(str, max_chars);
-
-    return ret;
-}    
-
-
-int xc_physinfo(int xc_handle,
-                xc_physinfo_t *put_info)
-{
-    int ret;
-    dom0_op_t op;
-    dom0_physinfo_t *got_info = &op.u.physinfo;
-    
-    op.cmd = DOM0_PHYSINFO;
-    op.interface_version = DOM0_INTERFACE_VERSION;
-
-    if((ret = do_dom0_op(xc_handle, &op))) return ret;
-
-    put_info->ht_per_core = got_info->ht_per_core;
-    put_info->cores       = got_info->cores;
-    put_info->total_pages = got_info->total_pages;
-    put_info->free_pages  = got_info->free_pages;
-    put_info->cpu_khz     = got_info->cpu_khz;
-
-    return 0;
-}
-
-
-int xc_sched_id(int xc_handle,
-                int *sched_id)
-{
-    int ret;
-    dom0_op_t op;
-    
-    op.cmd = DOM0_SCHED_ID;
-    op.interface_version = DOM0_INTERFACE_VERSION;
-    
-    if((ret = do_dom0_op(xc_handle, &op))) return ret;
-    
-    *sched_id = op.u.sched_id.sched_id;
-    
-    return 0;
-}
-
diff --git a/tools/xc/lib/xc_netbsd_build.c b/tools/xc/lib/xc_netbsd_build.c
deleted file mode 100644 (file)
index 04a47b5..0000000
+++ /dev/null
@@ -1,705 +0,0 @@
-/******************************************************************************
- * xc_netbsd_build.c
- */
-
-#include "xc_private.h"
-#define ELFSIZE 32  /* XXX */
-#include "xc_elf.h"
-#include <zlib.h>
-
-#ifdef DEBUG
-#define DPRINTF(x) printf x
-#else
-#define DPRINTF(x)
-#endif
-
-static int loadelfimage(gzFile, int, unsigned long *, unsigned long,
-                        unsigned long *, unsigned long *,
-                        unsigned long *, unsigned long *);
-
-#define ELFROUND (ELFSIZE / 8)
-
-#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
-#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-
-static long get_tot_pages(int xc_handle, u32 domid)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_GETDOMAININFO;
-    op.u.getdomaininfo.domain = (domid_t)domid;
-    op.u.getdomaininfo.ctxt = NULL;
-    return (do_dom0_op(xc_handle, &op) < 0) ? 
-        -1 : op.u.getdomaininfo.tot_pages;
-}
-
-static int get_pfn_list(int xc_handle,
-                        u32 domid, 
-                        unsigned long *pfn_buf, 
-                        unsigned long max_pfns)
-{
-    dom0_op_t op;
-    int ret;
-    op.cmd = DOM0_GETMEMLIST;
-    op.u.getmemlist.domain   = (domid_t)domid;
-    op.u.getmemlist.max_pfns = max_pfns;
-    op.u.getmemlist.buffer   = pfn_buf;
-
-    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
-        return -1;
-
-    ret = do_dom0_op(xc_handle, &op);
-
-    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
-
-    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
-}
-
-static int setup_guestos(int xc_handle,
-                         u32 dom, 
-                         gzFile kernel_gfd, 
-                         unsigned long tot_pages,
-                         unsigned long *virt_startinfo_addr, 
-                         unsigned long *virt_load_addr, 
-                         full_execution_context_t *ctxt,
-                         const char *cmdline,
-                         unsigned long shared_info_frame,
-                         unsigned int control_evtchn)
-{
-    l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
-    l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
-    unsigned long *page_array = NULL;
-    int alloc_index, num_pt_pages;
-    unsigned long l2tab;
-    unsigned long l1tab;
-    unsigned long count, pt_start;
-    unsigned long symtab_addr = 0, symtab_len = 0;
-    extended_start_info_t *start_info;
-    shared_info_t *shared_info;
-    unsigned long ksize;
-    mmu_t *mmu = NULL;
-    int pm_handle, i;
-
-    if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 )
-        goto error_out;
-
-    if ( (page_array = malloc(tot_pages * sizeof(unsigned long))) == NULL )
-    {
-        PERROR("Could not allocate memory");
-        goto error_out;
-    }
-
-    if ( get_pfn_list(xc_handle, dom, page_array, tot_pages) != tot_pages )
-    {
-        PERROR("Could not get the page frame list");
-        goto error_out;
-    }
-
-    if (loadelfimage(kernel_gfd, pm_handle, page_array, tot_pages,
-                     virt_load_addr, &ksize, &symtab_addr, &symtab_len))
-        goto error_out;
-
-    /* ksize is kernel-image size rounded up to a page boundary. */
-
-    alloc_index = tot_pages - 1;
-
-    /* Count bottom-level PTs, rounding up. */
-    num_pt_pages = (l1_table_offset(*virt_load_addr) + tot_pages + 1023)
-        / 1024;
-
-    /* We must also count the page directory. */
-    num_pt_pages++;
-
-    /* Index of first PT page. */
-    pt_start = tot_pages - num_pt_pages;
-
-    /*
-     * First allocate page for page dir. Allocation goes backwards from the end
-     * of the allocated physical address space.
-     */
-    l2tab = page_array[alloc_index] << PAGE_SHIFT;
-    alloc_index--;
-    ctxt->pt_base = l2tab;
-    
-    if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL )
-        goto error_out;
-    
-    /* Initialise the page tables. */
-    if ( (vl2tab = map_pfn_writeable(pm_handle, l2tab >> PAGE_SHIFT)) == NULL )
-        goto error_out;
-    memset(vl2tab, 0, PAGE_SIZE);
-    vl2e = &vl2tab[l2_table_offset(*virt_load_addr)];
-    for ( count = 0; count < tot_pages; count++ )
-    {
-        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
-        {
-            l1tab = page_array[alloc_index--] << PAGE_SHIFT;
-            if ( vl1tab != NULL )
-                unmap_pfn(pm_handle, vl1tab);
-            if ( (vl1tab = map_pfn_writeable(pm_handle,
-                                             l1tab >> PAGE_SHIFT)) == NULL )
-                goto error_out;
-            memset(vl1tab, 0, PAGE_SIZE);
-            vl1e = &vl1tab[l1_table_offset(*virt_load_addr + 
-                                           (count<<PAGE_SHIFT))];
-            *vl2e++ = l1tab | L2_PROT;
-        }
-
-        *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
-        if ( count >= pt_start )
-            *vl1e &= ~_PAGE_RW;
-        vl1e++;
-
-        if ( add_mmu_update(xc_handle, mmu,
-                            (page_array[count] << PAGE_SHIFT) | 
-                            MMU_MACHPHYS_UPDATE, count) )
-            goto error_out;
-    }
-    unmap_pfn(pm_handle, vl1tab);
-    unmap_pfn(pm_handle, vl2tab);
-
-    /*
-     * Pin down l2tab addr as page dir page - causes hypervisor to provide
-     * correct protection for the page
-     */ 
-    if ( add_mmu_update(xc_handle, mmu,
-                        l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L2_TABLE) )
-        goto error_out;
-
-    *virt_startinfo_addr =
-        *virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
-
-    start_info = map_pfn_writeable(pm_handle, page_array[alloc_index-1]);
-    memset(start_info, 0, sizeof(*start_info));
-    start_info->pt_base     = *virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
-    start_info->mod_start   = symtab_addr;
-    start_info->mod_len     = symtab_len;
-    start_info->nr_pages    = tot_pages;
-    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
-    start_info->flags       = 0;
-    start_info->domain_controller_evtchn = control_evtchn;
-    strncpy(start_info->cmd_line, cmdline, MAX_CMDLINE);
-    start_info->cmd_line[MAX_CMDLINE-1] = '\0';
-    unmap_pfn(pm_handle, start_info);
-
-    /* shared_info page starts its life empty. */
-    shared_info = map_pfn_writeable(pm_handle, shared_info_frame);
-    memset(shared_info, 0, PAGE_SIZE);
-    /* Mask all upcalls... */
-    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
-        shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
-    unmap_pfn(pm_handle, shared_info);
-
-    /* Send the page update requests down to the hypervisor. */
-    if ( finish_mmu_updates(xc_handle, mmu) )
-        goto error_out;
-
-    free(mmu);
-    (void)close_pfn_mapper(pm_handle);
-    free(page_array);
-    return 0;
-
- error_out:
-    if ( mmu != NULL )
-        free(mmu);
-    if ( pm_handle >= 0 )
-        (void)close_pfn_mapper(pm_handle);
-    if ( page_array == NULL )
-        free(page_array);
-    return -1;
-}
-
-int xc_netbsd_build(int xc_handle,
-                    u32 domid,
-                    const char *image_name,
-                    const char *cmdline,
-                    unsigned int control_evtchn)
-{
-    dom0_op_t launch_op, op;
-    unsigned long load_addr;
-    long tot_pages;
-    int kernel_fd = -1;
-    gzFile kernel_gfd = NULL;
-    int rc, i;
-    full_execution_context_t st_ctxt, *ctxt = &st_ctxt;
-    unsigned long virt_startinfo_addr;
-
-    if ( (tot_pages = get_tot_pages(xc_handle, domid)) < 0 )
-    {
-        PERROR("Could not find total pages for domain");
-        return 1;
-    }
-
-    kernel_fd = open(image_name, O_RDONLY);
-    if ( kernel_fd < 0 )
-    {
-        PERROR("Could not open kernel image");
-        return 1;
-    }
-
-    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
-    {
-        PERROR("Could not allocate decompression state for state file");
-        close(kernel_fd);
-        return 1;
-    }
-
-    if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
-    {   
-        PERROR("Unable to mlock ctxt");
-        return 1;
-    }
-
-    op.cmd = DOM0_GETDOMAININFO;
-    op.u.getdomaininfo.domain = (domid_t)domid;
-    op.u.getdomaininfo.ctxt = ctxt;
-    if ( (do_dom0_op(xc_handle, &op) < 0) || 
-         ((u32)op.u.getdomaininfo.domain != domid) )
-    {
-        PERROR("Could not get info on domain");
-        goto error_out;
-    }
-    if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ||
-         (op.u.getdomaininfo.ctxt->pt_base != 0) )
-    {
-        ERROR("Domain is already constructed");
-        goto error_out;
-    }
-
-    if ( setup_guestos(xc_handle, domid, kernel_gfd, tot_pages,
-                       &virt_startinfo_addr,
-                       &load_addr, &st_ctxt, cmdline,
-                       op.u.getdomaininfo.shared_info_frame,
-                       control_evtchn) < 0 )
-    {
-        ERROR("Error constructing guest OS");
-        goto error_out;
-    }
-
-    if ( kernel_fd >= 0 )
-        close(kernel_fd);
-    if( kernel_gfd )
-        gzclose(kernel_gfd);
-
-    ctxt->flags = 0;
-
-    /*
-     * Initial register values:
-     *  DS,ES,FS,GS = FLAT_GUESTOS_DS
-     *       CS:EIP = FLAT_GUESTOS_CS:start_pc
-     *       SS:ESP = FLAT_GUESTOS_DS:start_stack
-     *          ESI = start_info
-     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
-     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
-     */
-    ctxt->cpu_ctxt.ds = FLAT_GUESTOS_DS;
-    ctxt->cpu_ctxt.es = FLAT_GUESTOS_DS;
-    ctxt->cpu_ctxt.fs = FLAT_GUESTOS_DS;
-    ctxt->cpu_ctxt.gs = FLAT_GUESTOS_DS;
-    ctxt->cpu_ctxt.ss = FLAT_GUESTOS_DS;
-    ctxt->cpu_ctxt.cs = FLAT_GUESTOS_CS;
-    ctxt->cpu_ctxt.eip = load_addr;
-    ctxt->cpu_ctxt.esp = virt_startinfo_addr;
-    ctxt->cpu_ctxt.esi = virt_startinfo_addr;
-    ctxt->cpu_ctxt.eflags = (1<<9) | (1<<2);
-
-    /* FPU is set up to default initial state. */
-    memset(ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
-
-    /* Virtual IDT is empty at start-of-day. */
-    for ( i = 0; i < 256; i++ )
-    {
-        ctxt->trap_ctxt[i].vector = i;
-        ctxt->trap_ctxt[i].cs     = FLAT_GUESTOS_CS;
-    }
-    ctxt->fast_trap_idx = 0;
-
-    /* No LDT. */
-    ctxt->ldt_ents = 0;
-    
-    /* Use the default Xen-provided GDT. */
-    ctxt->gdt_ents = 0;
-
-    /* Ring 1 stack is the initial stack. */
-    ctxt->guestos_ss  = FLAT_GUESTOS_DS;
-    ctxt->guestos_esp = virt_startinfo_addr;
-
-    /* No debugging. */
-    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
-
-    /* No callback handlers. */
-    ctxt->event_callback_cs     = FLAT_GUESTOS_CS;
-    ctxt->event_callback_eip    = 0;
-    ctxt->failsafe_callback_cs  = FLAT_GUESTOS_CS;
-    ctxt->failsafe_callback_eip = 0;
-
-    memset( &launch_op, 0, sizeof(launch_op) );
-
-    launch_op.u.builddomain.domain   = (domid_t)domid;
-    launch_op.u.builddomain.ctxt = ctxt;
-    launch_op.cmd = DOM0_BUILDDOMAIN;
-    rc = do_dom0_op(xc_handle, &launch_op);
-    
-    return rc;
-
- error_out:
-    if ( kernel_fd >= 0 )
-        close(kernel_fd);
-    if( kernel_gfd )
-        gzclose(kernel_gfd);
-
-    return -1;
-}
-
-#define MYSEEK_BUFSIZE 1024
-static off_t
-myseek(gzFile gfd, off_t offset, int whence)
-{
-    unsigned char tmp[MYSEEK_BUFSIZE];
-    int c;
-
-    if ( offset < 0 )
-    {
-        ERROR("seek back not supported");
-        return -1;
-    }
-
-    while ( offset != 0 )
-    {
-        c = offset;
-        if ( c > MYSEEK_BUFSIZE )
-            c = MYSEEK_BUFSIZE;
-        if ( gzread(gfd, tmp, c) != c )
-        {
-            PERROR("Error seeking in image.");
-            return -1;
-        }
-        offset -= c;
-    }
-
-    return 0;   /* XXX */
-}
-
-/* 
- * NetBSD memory layout:
- *
- * ---------------- *virt_load_addr = ehdr.e_entry (0xc0100000)
- * | kernel text  |
- * |              |
- * ----------------
- * | kernel data  |
- * |              |
- * ----------------
- * | kernel bss   |
- * |              |
- * ---------------- *symtab_addr
- * | symtab size  |   = *symtab_len
- * ----------------
- * | elf header   |   offsets to symbol sections mangled to be relative
- * |              |   to headers location
- * ----------------
- * | sym section  |
- * | headers      |
- * ----------------
- * | sym sections |
- * |              |
- * ---------------- *symtab_addr + *symtab_len
- * | padding      |
- * ---------------- ehdr.e_entry + *ksize << PAGE_SHIFT
- */
-
-#define IS_TEXT(p) (p.p_flags & PF_X)
-#define IS_DATA(p) (p.p_flags & PF_W)
-#define IS_BSS(p) (p.p_filesz < p.p_memsz)
-
-static int
-loadelfimage(gzFile kernel_gfd, int pm_handle, unsigned long *page_array,
-             unsigned long tot_pages, unsigned long *virt_load_addr,
-             unsigned long *ksize, unsigned long *symtab_addr,
-             unsigned long *symtab_len)
-{
-    Elf_Ehdr ehdr;
-    Elf_Phdr *phdr;
-    Elf_Shdr *shdr;
-    void *vaddr;
-    char page[PAGE_SIZE], *p;
-    unsigned long iva, maxva, symva;
-    int c, curpos, h, i, ret, s;
-
-    ret = -1;
-    phdr = NULL;
-    p = NULL;
-    maxva = 0;
-
-    if ( gzread(kernel_gfd, &ehdr, sizeof(Elf_Ehdr)) != sizeof(Elf_Ehdr) )
-    {
-        PERROR("Error reading kernel image ELF header.");
-        goto out;
-    }
-    curpos = sizeof(Elf_Ehdr);
-
-    if ( !IS_ELF(ehdr) )
-    {
-        PERROR("Image does not have an ELF header.");
-        goto out;
-    }
-
-    *virt_load_addr = ehdr.e_entry;
-
-    if ( (*virt_load_addr & (PAGE_SIZE-1)) != 0 )
-    {
-        ERROR("We can only deal with page-aligned load addresses");
-        goto out;
-    }
-
-    if ( (*virt_load_addr + (tot_pages << PAGE_SHIFT)) > 
-         HYPERVISOR_VIRT_START )
-    {
-        ERROR("Cannot map all domain memory without hitting Xen space");
-        goto out;
-    }
-
-
-    phdr = malloc(ehdr.e_phnum * sizeof(Elf_Phdr));
-    if ( phdr == NULL )
-    {
-        ERROR("Cannot allocate memory for Elf_Phdrs");
-        goto out;
-    }
-
-    if ( myseek(kernel_gfd, ehdr.e_phoff - curpos, SEEK_SET) == -1 )
-    {
-        ERROR("Seek to program header failed");
-        goto out;
-    }
-    curpos = ehdr.e_phoff;
-
-    if ( gzread(kernel_gfd, phdr, ehdr.e_phnum * sizeof(Elf_Phdr)) !=
-         ehdr.e_phnum * sizeof(Elf_Phdr) )
-    {
-        PERROR("Error reading kernel image ELF program header.");
-        goto out;
-    }
-    curpos += ehdr.e_phnum * sizeof(Elf_Phdr);
-
-    /* Copy run-time 'load' segments that are writeable and/or executable. */
-    for ( h = 0; h < ehdr.e_phnum; h++ ) 
-    {
-        if ( (phdr[h].p_type != PT_LOAD) ||
-             ((phdr[h].p_flags & (PF_W|PF_X)) == 0) )
-            continue;
-
-        if ( IS_TEXT(phdr[h]) || IS_DATA(phdr[h]) )
-        {
-            if ( myseek(kernel_gfd, phdr[h].p_offset - curpos, 
-                        SEEK_SET) == -1 )
-            {
-                ERROR("Seek to section failed");
-                goto out;
-            }
-            curpos = phdr[h].p_offset;
-
-            for ( iva = phdr[h].p_vaddr;
-                  iva < phdr[h].p_vaddr + phdr[h].p_filesz; 
-                  iva += c)
-            {
-                c = PAGE_SIZE - (iva & (PAGE_SIZE - 1));
-                if (iva + c > phdr[h].p_vaddr + phdr[h].p_filesz)
-                    c = phdr[h].p_vaddr + phdr[h].p_filesz - iva;
-                if ( gzread(kernel_gfd, page, c) != c )
-                {
-                    PERROR("Error reading kernel image page.");
-                    goto out;
-                }
-                curpos += c;
-                vaddr = map_pfn_writeable(pm_handle, 
-                                          page_array[(iva - *virt_load_addr)
-                                                    >> PAGE_SHIFT]);
-                if ( vaddr == NULL )
-                {
-                    ERROR("Couldn't map guest memory");
-                    goto out;
-                }
-                DPRINTF(("copy page %p to %p, count 0x%x\n", (void *)iva,
-                         vaddr + (iva & (PAGE_SIZE - 1)), c));
-                memcpy(vaddr + (iva & (PAGE_SIZE - 1)), page, c);
-                unmap_pfn(pm_handle, vaddr);
-            }
-
-            if ( phdr[h].p_vaddr + phdr[h].p_filesz > maxva )
-                maxva = phdr[h].p_vaddr + phdr[h].p_filesz;
-        }
-
-        if ( IS_BSS(phdr[h]) )
-        {
-            /* XXX maybe clear phdr[h].p_memsz bytes from
-               phdr[h].p_vaddr + phdr[h].p_filesz ??? */
-            if (phdr[h].p_vaddr + phdr[h].p_memsz > maxva)
-                maxva = phdr[h].p_vaddr + phdr[h].p_memsz;
-            DPRINTF(("bss from %p to %p, maxva %p\n",
-                     (void *)(phdr[h].p_vaddr + phdr[h].p_filesz),
-                     (void *)(phdr[h].p_vaddr + phdr[h].p_memsz),
-                     (void *)maxva));
-        }
-    }
-
-    p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
-               ehdr.e_shnum * sizeof(Elf_Shdr));
-    if ( p == NULL )
-    {
-        ERROR("Cannot allocate memory for Elf_Shdrs");
-        goto out;
-    }
-
-    shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
-
-    if ( myseek(kernel_gfd, ehdr.e_shoff - curpos, SEEK_SET) == -1 )
-    {
-        ERROR("Seek to symbol header failed");
-        goto out;
-    }
-    curpos = ehdr.e_shoff;
-
-    if ( gzread(kernel_gfd, shdr, ehdr.e_shnum * sizeof(Elf_Shdr)) !=
-         ehdr.e_shnum * sizeof(Elf_Shdr) ) 
-    {
-        PERROR("Error reading kernel image ELF symbol header.");
-        goto out;
-    }
-    curpos += ehdr.e_shnum * sizeof(Elf_Shdr);
-
-    maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
-    symva = maxva;
-    maxva += sizeof(int);
-    *symtab_addr = maxva;
-    *symtab_len = 0;
-    maxva += sizeof(Elf_Ehdr) + ehdr.e_shnum * sizeof(Elf_Shdr);
-    maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
-
-    /* Copy kernel string / symbol tables into physical memory */
-    for ( h = 0; h < ehdr.e_shnum; h++ )
-    {
-        if ( shdr[h].sh_type == SHT_STRTAB )
-        {
-            /* Look for a strtab @i linked to symtab @h. */
-            for ( i = 0; i < ehdr.e_shnum; i++ )
-                if ( (shdr[i].sh_type == SHT_SYMTAB) &&
-                     (shdr[i].sh_link == h) )
-                    break;
-            /* Skip symtab @h if we found no corresponding strtab @i. */
-            if ( i == ehdr.e_shnum )
-            {
-                shdr[h].sh_offset = 0;
-                continue;
-            }
-        }
-
-        if ( (shdr[h].sh_type == SHT_STRTAB) ||
-             (shdr[h].sh_type == SHT_SYMTAB) )
-        {
-            if ( myseek(kernel_gfd, shdr[h].sh_offset - curpos, 
-                        SEEK_SET) == -1 )
-            {
-                ERROR("Seek to symbol section failed");
-                goto out;
-            }
-            curpos = shdr[h].sh_offset;
-
-            /* Mangled to be based on ELF header location. */
-            shdr[h].sh_offset = maxva - *symtab_addr;
-
-            DPRINTF(("copy section %d, size 0x%x\n", h, shdr[h].sh_size));
-            for ( i = 0; i < shdr[h].sh_size; i += c, maxva += c )
-            {
-                c = PAGE_SIZE - (maxva & (PAGE_SIZE - 1));
-                if ( c > (shdr[h].sh_size - i) )
-                    c = shdr[h].sh_size - i;
-                if ( gzread(kernel_gfd, page, c) != c )
-                {
-                    PERROR("Error reading kernel image page.");
-                    goto out;
-                }
-                curpos += c;
-
-                vaddr = map_pfn_writeable(pm_handle, 
-                                          page_array[(maxva - *virt_load_addr)
-                                                    >> PAGE_SHIFT]);
-                if ( vaddr == NULL )
-                {
-                    ERROR("Couldn't map guest memory");
-                    goto out;
-                }
-                DPRINTF(("copy page %p to %p, count 0x%x\n", (void *)maxva,
-                         vaddr + (maxva & (PAGE_SIZE - 1)), c));
-                memcpy(vaddr + (maxva & (PAGE_SIZE - 1)), page, c);
-                unmap_pfn(pm_handle, vaddr);
-            }
-
-            *symtab_len += shdr[h].sh_size;
-            maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
-
-        }
-        shdr[h].sh_name = 0;  /* Name is NULL. */
-    }
-
-    if ( *symtab_len == 0 ) 
-    {
-        DPRINTF(("no symbol table\n"));
-        *symtab_addr = 0;
-        ret = 0;
-        goto out;
-    }
-
-    DPRINTF(("sym header va %p from %p/%p size %x/%x\n", (void *)symva,
-             shdr, p, ehdr.e_shnum * sizeof(Elf_Shdr),
-             ehdr.e_shnum * sizeof(Elf_Shdr) + sizeof(Elf_Ehdr)));
-    ehdr.e_phoff = 0;
-    ehdr.e_shoff = sizeof(Elf_Ehdr);
-    ehdr.e_phentsize = 0;
-    ehdr.e_phnum = 0;
-    ehdr.e_shstrndx = SHN_UNDEF;
-    memcpy(p + sizeof(int), &ehdr, sizeof(Elf_Ehdr));
-    *(int *)p = maxva - *symtab_addr;
-
-    /* Copy total length, crafted ELF header and section header table */
-    s = sizeof(int) + sizeof(Elf_Ehdr) + ehdr.e_shnum * sizeof(Elf_Shdr);
-    for ( i = 0; i < s; i += c, symva += c ) 
-    {
-        c = PAGE_SIZE - (symva & (PAGE_SIZE - 1));
-        if ( c > s - i )
-            c = s - i;
-        vaddr = map_pfn_writeable(pm_handle, 
-                                  page_array[(symva - *virt_load_addr)
-                                            >> PAGE_SHIFT]);
-        if ( vaddr == NULL )
-        {
-            ERROR("Couldn't map guest memory");
-            goto out;
-        }
-        DPRINTF(("copy page %p to %p, count 0x%x\n", (void *)symva,
-                 vaddr + (symva & (PAGE_SIZE - 1)), c));
-        memcpy(vaddr + (symva & (PAGE_SIZE - 1)), p + i,
-               c);
-        unmap_pfn(pm_handle, vaddr);
-    }
-
-    *symtab_len = maxva - *symtab_addr;
-
-    ret = 0;
-
- out:
-    if ( ret == 0 )
-    {
-        maxva = (maxva + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
-        *ksize = (maxva - *virt_load_addr) >> PAGE_SHIFT;
-
-        DPRINTF(("virt_addr %p, kpages 0x%lx, symtab_addr %p, symtab_len %p\n",
-                 (void *)*virt_load_addr, *ksize, (void *)*symtab_addr,
-                 (void *)*symtab_len));
-    }
-
-    if ( phdr != NULL )
-        free(phdr);
-    if ( p != NULL )
-        free(p);
-    return ret;
-}
diff --git a/tools/xc/lib/xc_physdev.c b/tools/xc/lib/xc_physdev.c
deleted file mode 100644 (file)
index ba5dd9c..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/******************************************************************************
- * xc_physdev.c
- * 
- * API for manipulating physical-device access permissions.
- * 
- * Copyright (c) 2004, Rolf Neugebauer (Intel Research Cambridge)
- * Copyright (c) 2004, K A Fraser (University of Cambridge)
- */
-
-#include "xc_private.h"
-
-int xc_physdev_pci_access_modify(int xc_handle,
-                                 u32 domid,
-                                 int bus,
-                                 int dev,
-                                 int func,
-                                 int enable)
-{
-    dom0_op_t op;
-
-    op.cmd = DOM0_PCIDEV_ACCESS;
-    op.u.pcidev_access.domain = (domid_t)domid;
-    op.u.pcidev_access.bus    = bus;
-    op.u.pcidev_access.dev    = dev;
-    op.u.pcidev_access.func   = func;
-    op.u.pcidev_access.enable = enable;
-
-    return do_dom0_op(xc_handle, &op);
-}
diff --git a/tools/xc/lib/xc_private.c b/tools/xc/lib/xc_private.c
deleted file mode 100644 (file)
index 344f482..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/******************************************************************************
- * xc_private.c
- * 
- * Helper functions for the rest of the library.
- */
-
-#include "xc_private.h"
-
-int init_pfn_mapper(domid_t domid)
-{
-    int fd = open("/dev/mem", O_RDWR);
-    if ( fd >= 0 )
-        (void)ioctl(fd, _IO('M', 1), (unsigned long)domid);
-    return fd;
-}
-
-int close_pfn_mapper(int pm_handle)
-{
-    return close(pm_handle);
-}
-
-void *map_pfn_writeable(int pm_handle, unsigned long pfn)
-{
-    void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
-                       MAP_SHARED, pm_handle, pfn << PAGE_SHIFT);
-    if ( vaddr == MAP_FAILED )
-        return NULL;
-    return vaddr;
-}
-
-void *map_pfn_readonly(int pm_handle, unsigned long pfn)
-{
-    void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ,
-                       MAP_SHARED, pm_handle, pfn << PAGE_SHIFT);
-    if ( vaddr == MAP_FAILED )
-        return NULL;
-    return vaddr;
-}
-
-void unmap_pfn(int pm_handle, void *vaddr)
-{
-    (void)munmap(vaddr, PAGE_SIZE);
-}
-
-/*******************/
-
-void * mfn_mapper_map_batch(int xc_handle, domid_t dom, int prot,
-                            unsigned long *arr, int num )
-{
-    privcmd_mmapbatch_t ioctlx; 
-    void *addr;
-    addr = mmap( NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0 );
-    if (addr)
-    {
-        ioctlx.num=num;
-        ioctlx.dom=dom;
-        ioctlx.addr=(unsigned long)addr;
-        ioctlx.arr=arr;
-        if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx ) < 0 )
-        {
-            perror("XXXXXXXX");
-            munmap(addr, num*PAGE_SIZE);
-            return 0;
-        }
-    }
-    return addr;
-
-}
-
-/*******************/
-
-void * mfn_mapper_map_single(int xc_handle, domid_t dom,
-                             int size, int prot,
-                             unsigned long mfn )
-{
-    privcmd_mmap_t ioctlx; 
-    privcmd_mmap_entry_t entry; 
-    void *addr;
-    addr = mmap( NULL, size, prot, MAP_SHARED, xc_handle, 0 );
-    if (addr)
-    {
-        ioctlx.num=1;
-        ioctlx.dom=dom;
-        ioctlx.entry=&entry;
-        entry.va=(unsigned long) addr;
-        entry.mfn=mfn;
-        entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT;
-        if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) <0 )
-        {
-            munmap(addr, size);
-            return 0;
-        }
-    }
-    return addr;
-}
-
-/*******************/
-
-/* NB: arr must be mlock'ed */
-int get_pfn_type_batch(int xc_handle, 
-                       u32 dom, int num, unsigned long *arr)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_GETPAGEFRAMEINFO2;
-    op.u.getpageframeinfo2.domain = (domid_t)dom;
-    op.u.getpageframeinfo2.num    = num;
-    op.u.getpageframeinfo2.array  = arr;
-    return do_dom0_op(xc_handle, &op);
-}
-
-#define GETPFN_ERR (~0U)
-unsigned int get_pfn_type(int xc_handle, 
-                          unsigned long mfn, 
-                          u32 dom)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_GETPAGEFRAMEINFO;
-    op.u.getpageframeinfo.pfn    = mfn;
-    op.u.getpageframeinfo.domain = (domid_t)dom;
-    if ( do_dom0_op(xc_handle, &op) < 0 )
-    {
-        PERROR("Unexpected failure when getting page frame info!");
-        return GETPFN_ERR;
-    }
-    return op.u.getpageframeinfo.type;
-}
-
-
-
-/*******************/
-
-#define FIRST_MMU_UPDATE 1
-
-static int flush_mmu_updates(int xc_handle, mmu_t *mmu)
-{
-    int err = 0;
-    privcmd_hypercall_t hypercall;
-
-    if ( mmu->idx == FIRST_MMU_UPDATE )
-        return 0;
-
-    /* The first two requests set the correct subject domain (PTS and GPS). */
-    mmu->updates[0].val  = (unsigned long)(mmu->subject<<16) & ~0xFFFFUL;
-    mmu->updates[0].ptr  = (unsigned long)(mmu->subject<< 0) & ~0xFFFFUL;
-    mmu->updates[0].ptr |= MMU_EXTENDED_COMMAND;
-    mmu->updates[0].val |= MMUEXT_SET_SUBJECTDOM | SET_PAGETABLE_SUBJECTDOM;
-
-    hypercall.op     = __HYPERVISOR_mmu_update;
-    hypercall.arg[0] = (unsigned long)mmu->updates;
-    hypercall.arg[1] = (unsigned long)mmu->idx;
-    hypercall.arg[2] = 0;
-
-    if ( mlock(mmu->updates, sizeof(mmu->updates)) != 0 )
-    {
-        PERROR("Could not lock pagetable update array");
-        err = 1;
-        goto out;
-    }
-
-    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
-    {
-        ERROR("Failure when submitting mmu updates");
-        err = 1;
-    }
-
-    mmu->idx = FIRST_MMU_UPDATE;
-    
-    (void)munlock(mmu->updates, sizeof(mmu->updates));
-
- out:
-    return err;
-}
-
-mmu_t *init_mmu_updates(int xc_handle, domid_t dom)
-{
-    mmu_t *mmu = malloc(sizeof(mmu_t));
-    if ( mmu == NULL )
-        return mmu;
-    mmu->idx     = FIRST_MMU_UPDATE;
-    mmu->subject = dom;
-    return mmu;
-}
-
-int add_mmu_update(int xc_handle, mmu_t *mmu, 
-                   unsigned long ptr, unsigned long val)
-{
-    mmu->updates[mmu->idx].ptr = ptr;
-    mmu->updates[mmu->idx].val = val;
-
-    if ( ++mmu->idx == MAX_MMU_UPDATES )
-        return flush_mmu_updates(xc_handle, mmu);
-
-    return 0;
-}
-
-int finish_mmu_updates(int xc_handle, mmu_t *mmu)
-{
-    return flush_mmu_updates(xc_handle, mmu);
-}
-
-
-long long  xc_domain_get_cpu_usage( int xc_handle, domid_t domid )
-{
-    dom0_op_t op;
-
-    op.cmd = DOM0_GETDOMAININFO;
-    op.u.getdomaininfo.domain = (domid_t)domid;
-    op.u.getdomaininfo.ctxt = NULL;
-    if ( (do_dom0_op(xc_handle, &op) < 0) || 
-         ((u32)op.u.getdomaininfo.domain != domid) )
-    {
-        PERROR("Could not get info on domain");
-        return -1;
-    }
-    return op.u.getdomaininfo.cpu_time;
-}
-
-
-/* This is shared between save and restore, and may generally be useful. */
-unsigned long csum_page (void * page)
-{
-    int i;
-    unsigned long *p = page;
-    unsigned long long sum=0;
-
-    for ( i = 0; i < (PAGE_SIZE/sizeof(unsigned long)); i++ )
-        sum += p[i];
-
-    return sum ^ (sum>>32);
-}
diff --git a/tools/xc/lib/xc_private.h b/tools/xc/lib/xc_private.h
deleted file mode 100644 (file)
index 7421851..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-
-#ifndef __XC_PRIVATE_H__
-#define __XC_PRIVATE_H__
-
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <string.h>
-
-#include "xc.h"
-
-/* from xen/include/hypervisor-ifs */
-#include <hypervisor-if.h>
-#include <dom0_ops.h>
-#include <event_channel.h>
-#include <sched_ctl.h>
-
-#include <asm-xen/proc_cmd.h>
-
-/* from xend/lib */
-#include <domain_controller.h>
-
-#define _PAGE_PRESENT   0x001
-#define _PAGE_RW        0x002
-#define _PAGE_USER      0x004
-#define _PAGE_PWT       0x008
-#define _PAGE_PCD       0x010
-#define _PAGE_ACCESSED  0x020
-#define _PAGE_DIRTY     0x040
-#define _PAGE_PAT       0x080
-#define _PAGE_PSE       0x080
-#define _PAGE_GLOBAL    0x100
-
-
-#define L1_PAGETABLE_SHIFT       12
-#define L2_PAGETABLE_SHIFT       22
-#define ENTRIES_PER_L1_PAGETABLE 1024
-#define ENTRIES_PER_L2_PAGETABLE 1024
-#define PAGE_SHIFT              L1_PAGETABLE_SHIFT
-#define PAGE_SIZE               (1UL << PAGE_SHIFT)
-#define PAGE_MASK               (~(PAGE_SIZE-1))
-
-typedef unsigned long l1_pgentry_t;
-typedef unsigned long l2_pgentry_t;
-
-#define l1_table_offset(_a) \
-          (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
-#define l2_table_offset(_a) \
-          ((_a) >> L2_PAGETABLE_SHIFT)
-
-#define ERROR(_m, _a...)  \
-    fprintf(stderr, "ERROR: " _m "\n" , ## _a )
-
-#define PERROR(_m, _a...) \
-    fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
-            errno, strerror(errno))
-
-static inline int do_privcmd(int xc_handle,
-                             unsigned int cmd, 
-                             unsigned long data)
-{
-    return ioctl(xc_handle, cmd, data);
-}
-
-static inline int do_xen_hypercall(int xc_handle,
-                                   privcmd_hypercall_t *hypercall)
-{
-    return do_privcmd(xc_handle,
-                      IOCTL_PRIVCMD_HYPERCALL, 
-                      (unsigned long)hypercall);
-}
-
-static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
-{
-    int ret = -1;
-    privcmd_hypercall_t hypercall;
-
-    op->interface_version = DOM0_INTERFACE_VERSION;
-
-    hypercall.op     = __HYPERVISOR_dom0_op;
-    hypercall.arg[0] = (unsigned long)op;
-
-    if ( mlock(op, sizeof(*op)) != 0 )
-    {
-        PERROR("Could not lock memory for Xen hypercall");
-        goto out1;
-    }
-
-    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
-    {
-        if ( errno == EACCES )
-            fprintf(stderr, "Dom0 operation failed -- need to"
-                    " rebuild the user-space tool set?\n");
-        goto out2;
-    }
-
- out2: (void)munlock(op, sizeof(*op));
- out1: return ret;
-}
-
-static inline int do_multicall_op(int xc_handle, 
-                                 void *call_list, int nr_calls) 
-{
-    int ret = -1;
-    privcmd_hypercall_t hypercall;
-
-    hypercall.op     = __HYPERVISOR_multicall;
-    hypercall.arg[0] = (unsigned long)call_list;
-    hypercall.arg[1] = (unsigned long)nr_calls;
-
-    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
-    {
-        if ( errno == EACCES )
-            fprintf(stderr, "Dom0 operation failed -- need to"
-                    " rebuild the user-space tool set?\n");
-        goto out1;
-    }
-
- out1: return ret;
-}
-
-/*
- * PFN mapping.
- */
-int init_pfn_mapper(domid_t domid);
-int close_pfn_mapper(int pm_handle);
-void *map_pfn_writeable(int pm_handle, unsigned long pfn);
-void *map_pfn_readonly(int pm_handle, unsigned long pfn);
-void unmap_pfn(int pm_handle, void *vaddr);
-int get_pfn_type_batch(int xc_handle, u32 dom, int num, unsigned long *arr);
-unsigned long csum_page (void * page);
-
-/*
- * MMU updates.
- */
-#define MAX_MMU_UPDATES 1024
-typedef struct {
-    mmu_update_t updates[MAX_MMU_UPDATES];
-    int          idx;
-    domid_t      subject;
-} mmu_t;
-mmu_t *init_mmu_updates(int xc_handle, domid_t dom);
-int add_mmu_update(int xc_handle, mmu_t *mmu, 
-                   unsigned long ptr, unsigned long val);
-int finish_mmu_updates(int xc_handle, mmu_t *mmu);
-
-
-/*
- * ioctl-based mfn mapping interface
- */
-
-/*
-typedef struct privcmd_mmap_entry {
-    unsigned long va;
-    unsigned long mfn;
-    unsigned long npages;
-} privcmd_mmap_entry_t; 
-
-typedef struct privcmd_mmap {
-    int num;
-    domid_t dom;
-    privcmd_mmap_entry_t *entry;
-} privcmd_mmap_t; 
-*/
-
-#define mfn_mapper_queue_size 128
-
-typedef struct mfn_mapper {
-    int xc_handle;
-    int size;
-    int prot;
-    int error;
-    int max_queue_size;
-    void * addr;
-    privcmd_mmap_t ioctl; 
-    
-} mfn_mapper_t;
-
-void * mfn_mapper_map_single(int xc_handle, domid_t dom, int size, int prot, 
-                            unsigned long mfn );
-
-void * mfn_mapper_map_batch(int xc_handle, domid_t dom, int prot,
-                           unsigned long *arr, int num );
-
-mfn_mapper_t * mfn_mapper_init(int xc_handle, domid_t dom, int size, int prot);
-
-void * mfn_mapper_base(mfn_mapper_t *t);
-
-void mfn_mapper_close(mfn_mapper_t *t);
-
-int mfn_mapper_flush_queue(mfn_mapper_t *t);
-
-void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, 
-                             unsigned long mfn, int size );
-
-long long  xc_domain_get_cpu_usage( int xc_handle, domid_t domid );
-
-#include "xc_io.h"
-
-int xc_domain_getfullinfo(int xc_handle,
-                          u32 domid,
-                          dom0_op_t *op,
-                          full_execution_context_t *ctxt );
-#endif /* __XC_PRIVATE_H__ */
diff --git a/tools/xc/lib/xc_rrobin.c b/tools/xc/lib/xc_rrobin.c
deleted file mode 100644 (file)
index ad37962..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/******************************************************************************
- * xc_rrobin.c
- * 
- * API for manipulating parameters of the Round Robin scheduler
- * 
- * by Mark Williamson, Copyright (c) 2004 Intel Research Cambridge.
- */
-
-#include "xc_private.h"
-
-int xc_rrobin_global_set(int xc_handle, u64 slice)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_SCHEDCTL;
-    op.u.schedctl.sched_id = SCHED_RROBIN;
-    op.u.schedctl.direction = SCHED_INFO_PUT;
-
-    op.u.schedctl.u.rrobin.slice = slice;
-    return do_dom0_op(xc_handle, &op);
-}
-
-
-int xc_rrobin_global_get(int xc_handle, u64 *slice)
-{
-    dom0_op_t op;
-    int ret;
-
-    op.cmd = DOM0_SCHEDCTL;
-    op.u.schedctl.sched_id = SCHED_RROBIN;
-    op.u.schedctl.direction = SCHED_INFO_GET;
-
-    ret = do_dom0_op(xc_handle, &op);
-
-    *slice = op.u.schedctl.u.rrobin.slice;
-
-    return ret;
-}
diff --git a/tools/xc/py/Makefile b/tools/xc/py/Makefile
deleted file mode 100644 (file)
index 7dc74a1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-all:
-       python setup.py build
-
-install: all
-       if [ "$(prefix)" = "" ]; then                   \
-           python setup.py install;                    \
-       elif [ "$(dist)" = "yes" ]; then                \
-           python setup.py install --home="$(prefix)"; \
-       else                                            \
-           python setup.py install --root="$(prefix)"; \
-       fi
-
-clean:
-       rm -rf build *.pyc *.pyo *.o *.a *~
diff --git a/tools/xc/py/Xc.c b/tools/xc/py/Xc.c
deleted file mode 100644 (file)
index 2eb70cf..0000000
+++ /dev/null
@@ -1,1160 +0,0 @@
-/******************************************************************************
- * Xc.c
- * 
- * Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
- */
-
-#include <Python.h>
-#include <xc.h>
-#include <zlib.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include "xc_private.h"
-#include "gzip_stream.h"
-
-/* Needed for Python versions earlier than 2.3. */
-#ifndef PyMODINIT_FUNC
-#define PyMODINIT_FUNC DL_EXPORT(void)
-#endif
-
-#define XENPKG "xen.ext.xc"
-
-static PyObject *xc_error, *zero;
-
-typedef struct {
-    PyObject_HEAD;
-    int xc_handle;
-} XcObject;
-
-/*
- * Definitions for the 'xc' object type.
- */
-
-static PyObject *pyxc_domain_create(PyObject *self,
-                                    PyObject *args,
-                                    PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    unsigned int mem_kb = 0;
-    char        *name   = "(anon)";
-    int          cpu = -1;
-    u32          dom;
-    int          ret;
-
-    static char *kwd_list[] = { "mem_kb", "name", "cpu", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|isi", kwd_list, 
-                                      &mem_kb, &name, &cpu) )
-        return NULL;
-
-    if ( (ret = xc_domain_create(xc->xc_handle, mem_kb, name, cpu, &dom)) < 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    return PyInt_FromLong(dom);
-}
-
-static PyObject *pyxc_domain_pause(PyObject *self,
-                                   PyObject *args,
-                                   PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-
-    static char *kwd_list[] = { "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
-        return NULL;
-
-    if ( xc_domain_pause(xc->xc_handle, dom) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_domain_unpause(PyObject *self,
-                                     PyObject *args,
-                                     PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-
-    static char *kwd_list[] = { "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
-        return NULL;
-
-    if ( xc_domain_unpause(xc->xc_handle, dom) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_domain_destroy(PyObject *self,
-                                     PyObject *args,
-                                     PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-
-    static char *kwd_list[] = { "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
-        return NULL;
-
-    if ( xc_domain_destroy(xc->xc_handle, dom) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_domain_pincpu(PyObject *self,
-                                    PyObject *args,
-                                    PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-    int cpu = -1;
-
-    static char *kwd_list[] = { "dom", "cpu", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
-                                      &dom, &cpu) )
-        return NULL;
-
-    if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_domain_getinfo(PyObject *self,
-                                     PyObject *args,
-                                     PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    PyObject *list;
-
-    u32 first_dom = 0;
-    int max_doms = 1024, nr_doms, i;
-    xc_dominfo_t *info;
-
-    static char *kwd_list[] = { "first_dom", "max_doms", NULL };
-    
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
-                                      &first_dom, &max_doms) )
-        return NULL;
-
-    if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
-        return PyErr_NoMemory();
-
-    nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
-    
-    list = PyList_New(nr_doms);
-    for ( i = 0 ; i < nr_doms; i++ )
-    {
-        PyList_SetItem(
-            list, i, 
-            Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
-                          ",s:l,s:L,s:s,s:l,s:i}",
-                          "dom",       info[i].domid,
-                          "cpu",       info[i].cpu,
-                          "dying",     info[i].dying,
-                          "crashed",   info[i].crashed,
-                          "shutdown",  info[i].shutdown,
-                          "paused",    info[i].paused,
-                          "blocked",   info[i].blocked,
-                          "running",   info[i].running,
-                          "mem_kb",    info[i].nr_pages*4,
-                          "cpu_time",  info[i].cpu_time,
-                          "name",      info[i].name,
-                          "maxmem_kb", info[i].max_memkb,
-                          "shutdown_reason", info[i].shutdown_reason
-                ));
-    }
-
-    free(info);
-
-    return list;
-}
-
-static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file){
-    int rc = -1;
-    int fd = -1;
-    int open_flags = (O_CREAT | O_EXCL | O_WRONLY);
-    int open_mode = 0644;
-
-    printf("%s>\n", __FUNCTION__);
-    fd = open(state_file, open_flags, open_mode);
-    if(fd < 0){
-        xcio_perror(ctxt, "Could not open file for writing");
-        goto exit;
-    }
-    /* Compression rate 1: we want speed over compression. 
-     * We're mainly going for those zero pages, after all.
-     */
-    printf("%s>gzip_stream_fdopen... \n", __FUNCTION__);
-    ctxt->io = gzip_stream_fdopen(fd, "wb1");
-    if(!ctxt->io){
-        xcio_perror(ctxt, "Could not allocate compression state");
-        goto exit;
-    }
-    printf("%s> xc_linux_save...\n", __FUNCTION__);
-    rc = xc_linux_save(xc->xc_handle, ctxt);
-  exit:
-    if(ctxt->io) IOStream_close(ctxt->io);
-    if(fd >= 0) close(fd);
-    unlink(state_file);
-    printf("%s> rc=%d\n", __FUNCTION__, rc);
-    return rc;
-}
-
-static PyObject *pyxc_linux_save(PyObject *self,
-                                 PyObject *args,
-                                 PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-    char *state_file;
-    int progress = 1, debug = 0;
-    unsigned int flags = 0;
-    PyObject *val = NULL;
-    int rc = -1;
-    XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
-
-    static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL };
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|sii", kwd_list, 
-                                     &ioctxt.domain,
-                                     &state_file,
-                                     &ioctxt.vmconfig,
-                                     &progress, 
-                                     &debug)){
-        goto exit;
-    }
-    ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0);
-    if (progress)  ioctxt.flags |= XCFLAGS_VERBOSE;
-    if (debug)     ioctxt.flags |= XCFLAGS_DEBUG;
-    if(!state_file || state_file[0] == '\0') goto exit;
-    rc = file_save(xc, &ioctxt, state_file);
-    if(rc){
-        PyErr_SetFromErrno(xc_error);
-        goto exit;
-    } 
-    //xc_domain_destroy(xc->xc_handle, dom);
-    Py_INCREF(zero);
-    val = zero;
-  exit:
-    return val;
-}
-
-
-static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file){
-    int rc = -1;
-
-    ioctxt->io = gzip_stream_fopen(state_file, "rb");
-    if (!ioctxt->io) {
-        xcio_perror(ioctxt, "Could not open file for reading");
-        goto exit;
-    }
-
-    rc = xc_linux_restore(xc->xc_handle, ioctxt);
-  exit:
-    if(ioctxt->io) IOStream_close(ioctxt->io);
-    return rc;
-}
-
-static PyObject *pyxc_linux_restore(PyObject *self,
-                                    PyObject *args,
-                                    PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    char *state_file;
-    int progress = 1, debug = 0;
-    u32 dom;
-    PyObject *val = NULL;
-    XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
-    int rc =-1;
-
-    static char *kwd_list[] = { "state_file", "progress", "debug", NULL };
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|ii", kwd_list, 
-                                     &ioctxt.domain,
-                                     &state_file,
-                                     &progress,
-                                     &debug)){
-        goto exit;
-    }
-    if (progress) ioctxt.flags |= XCFLAGS_VERBOSE;
-    if (debug)    ioctxt.flags |= XCFLAGS_DEBUG;
-
-    if(!state_file || state_file[0] == '\0') goto exit;
-    rc = file_restore(xc, &ioctxt, state_file);
-    if(rc){
-        PyErr_SetFromErrno(xc_error);
-        goto exit;
-    }
-    val = Py_BuildValue("{s:i,s:s}",
-                        "dom", ioctxt.domain,
-                        "vmconfig", ioctxt.vmconfig);
-    //? free(ioctxt.vmconfig);
-  exit:
-    return val;
-}
-
-static PyObject *pyxc_linux_build(PyObject *self,
-                                  PyObject *args,
-                                  PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32   dom;
-    char *image, *ramdisk = NULL, *cmdline = "";
-    int   control_evtchn, flags = 0;
-
-    static char *kwd_list[] = { "dom", "control_evtchn", 
-                                "image", "ramdisk", "cmdline", "flags",
-                                NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, 
-                                      &dom, &control_evtchn, 
-                                      &image, &ramdisk, &cmdline, &flags) )
-        return NULL;
-
-    if ( xc_linux_build(xc->xc_handle, dom, image,
-                        ramdisk, cmdline, control_evtchn, flags) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_netbsd_build(PyObject *self,
-                                   PyObject *args,
-                                   PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32   dom;
-    char *image, *ramdisk = NULL, *cmdline = "";
-    int   control_evtchn;
-
-    static char *kwd_list[] = { "dom", "control_evtchn",
-                                "image", "ramdisk", "cmdline", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, 
-                                      &dom, &control_evtchn,
-                                      &image, &ramdisk, &cmdline) )
-        return NULL;
-
-    if ( xc_netbsd_build(xc->xc_handle, dom, image, 
-                         cmdline, control_evtchn) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_bvtsched_global_set(PyObject *self,
-                                          PyObject *args,
-                                          PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    unsigned long ctx_allow;
-
-    static char *kwd_list[] = { "ctx_allow", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
-        return NULL;
-
-    if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_bvtsched_global_get(PyObject *self,
-                                          PyObject *args,
-                                          PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    
-    unsigned long ctx_allow;
-    
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-    
-    if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
-}
-
-static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
-                                          PyObject *args,
-                                          PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32           dom;
-    unsigned long mcuadv, warp, warpl, warpu;
-
-    static char *kwd_list[] = { "dom", "mcuadv", "warp", "warpl",
-                                "warpu", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illll", kwd_list,
-                                      &dom, &mcuadv, &warp, &warpl, &warpu) )
-        return NULL;
-
-    if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv, 
-                                warp, warpl, warpu) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
-                                          PyObject *args,
-                                          PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u32 dom;
-    unsigned long mcuadv, warp, warpl, warpu;
-    
-    static char *kwd_list[] = { "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
-        return NULL;
-    
-    if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warp,
-                                &warpl, &warpu) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
-                         "domain", dom,
-                         "mcuadv", mcuadv,
-                         "warp",   warp,
-                         "warpl",  warpl,
-                         "warpu",  warpu);
-}
-
-static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
-                                              PyObject *args,
-                                              PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
-    int port1, port2;
-
-    static char *kwd_list[] = { "dom1", "dom2", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list, 
-                                      &dom1, &dom2) )
-        return NULL;
-
-    if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1, 
-                                    dom2, &port1, &port2) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    return Py_BuildValue("{s:i,s:i}", 
-                         "port1", port1,
-                         "port2", port2);
-}
-
-static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
-                                       PyObject *args,
-                                       PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    int virq, port;
-
-    static char *kwd_list[] = { "virq", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
-        return NULL;
-
-    if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    return PyInt_FromLong(port);
-}
-
-static PyObject *pyxc_evtchn_close(PyObject *self,
-                                   PyObject *args,
-                                   PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom = DOMID_SELF;
-    int port;
-
-    static char *kwd_list[] = { "port", "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
-                                      &port, &dom) )
-        return NULL;
-
-    if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_evtchn_send(PyObject *self,
-                                  PyObject *args,
-                                  PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    int port;
-
-    static char *kwd_list[] = { "port", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
-        return NULL;
-
-    if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_evtchn_status(PyObject *self,
-                                    PyObject *args,
-                                    PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    PyObject *dict;
-
-    u32 dom = DOMID_SELF;
-    int port, ret;
-    xc_evtchn_status_t status;
-
-    static char *kwd_list[] = { "port", "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
-                                      &port, &dom) )
-        return NULL;
-
-    ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
-    if ( ret != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    switch ( status.status )
-    {
-    case EVTCHNSTAT_closed:
-        dict = Py_BuildValue("{s:s}", 
-                             "status", "closed");
-        break;
-    case EVTCHNSTAT_unbound:
-        dict = Py_BuildValue("{s:s}", 
-                             "status", "unbound");
-        break;
-    case EVTCHNSTAT_interdomain:
-        dict = Py_BuildValue("{s:s,s:i,s:i}", 
-                             "status", "interdomain",
-                             "dom", status.u.interdomain.dom,
-                             "port", status.u.interdomain.port);
-        break;
-    case EVTCHNSTAT_pirq:
-        dict = Py_BuildValue("{s:s,s:i}", 
-                             "status", "pirq",
-                             "irq", status.u.pirq);
-        break;
-    case EVTCHNSTAT_virq:
-        dict = Py_BuildValue("{s:s,s:i}", 
-                             "status", "virq",
-                             "irq", status.u.virq);
-        break;
-    default:
-        dict = Py_BuildValue("{}");
-        break;
-    }
-    
-    return dict;
-}
-
-static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
-                                                PyObject *args,
-                                                PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u32 dom;
-    int bus, dev, func, enable, ret;
-
-    static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list, 
-                                      &dom, &bus, &dev, &func, &enable) )
-        return NULL;
-
-    ret = xc_physdev_pci_access_modify(
-        xc->xc_handle, dom, bus, dev, func, enable);
-    if ( ret != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_readconsolering(PyObject *self,
-                                      PyObject *args,
-                                      PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    unsigned int clear = 0;
-    char         str[32768];
-    int          ret;
-
-    static char *kwd_list[] = { "clear", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
-        return NULL;
-
-    ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
-    if ( ret < 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    return PyString_FromStringAndSize(str, ret);
-}
-
-static PyObject *pyxc_physinfo(PyObject *self,
-                               PyObject *args,
-                               PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    xc_physinfo_t info;
-    
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( xc_physinfo(xc->xc_handle, &info) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
-                         "ht_per_core", info.ht_per_core,
-                         "cores",       info.cores,
-                         "total_pages", info.total_pages,
-                         "free_pages",  info.free_pages,
-                         "cpu_khz",     info.cpu_khz);
-}
-
-static PyObject *pyxc_atropos_domain_set(PyObject *self,
-                                         PyObject *args,
-                                         PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u32 domid;
-    u64 period, slice, latency;
-    int xtratime;
-
-    static char *kwd_list[] = { "dom", "period", "slice", "latency",
-                                "xtratime", NULL };
-    
-    if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLi", kwd_list, &domid,
-                                     &period, &slice, &latency, &xtratime) )
-        return NULL;
-   
-    if ( xc_atropos_domain_set(xc->xc_handle, domid, period, slice,
-                               latency, xtratime) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_atropos_domain_get(PyObject *self,
-                                         PyObject *args,
-                                         PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u32 domid;
-    u64 period, slice, latency;
-    int xtratime;
-    
-    static char *kwd_list[] = { "dom", NULL };
-
-    if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
-        return NULL;
-    
-    if ( xc_atropos_domain_get( xc->xc_handle, domid, &period,
-                                &slice, &latency, &xtratime ) )
-        return PyErr_SetFromErrno(xc_error);
-
-    return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
-                         "domain",  domid,
-                         "period",  period,
-                         "slice",   slice,
-                         "latency", latency,
-                         "xtratime", xtratime);
-}
-
-
-static PyObject *pyxc_rrobin_global_set(PyObject *self,
-                                        PyObject *args,
-                                        PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u64 slice;
-    
-    static char *kwd_list[] = { "slice", NULL };
-
-    if( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &slice) )
-        return NULL;
-    
-    if ( xc_rrobin_global_set(xc->xc_handle, slice) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_shadow_control(PyObject *self,
-                                     PyObject *args,
-                                     PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-    int op=0;
-
-    static char *kwd_list[] = { "dom", "op", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
-                                      &dom, &op) )
-        return NULL;
-
-    if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_rrobin_global_get(PyObject *self,
-                                        PyObject *args,
-                                        PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u64 slice;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( xc_rrobin_global_get(xc->xc_handle, &slice) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    return Py_BuildValue("{s:L}", "slice", slice);
-}
-
-static PyObject *pyxc_domain_setname(PyObject *self,
-                                     PyObject *args,
-                                     PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-    u32 dom;
-    char *name;
-
-    static char *kwd_list[] = { "dom", "name", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is", kwd_list, 
-                                      &dom, &name) )
-        return NULL;
-
-    if ( xc_domain_setname(xc->xc_handle, dom, name) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-static PyObject *pyxc_domain_setmaxmem(PyObject *self,
-                                       PyObject *args,
-                                       PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    u32 dom;
-    unsigned long max_memkb;
-
-    static char *kwd_list[] = { "dom", "max_memkb", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, 
-                                      &dom, &max_memkb) )
-        return NULL;
-
-    if ( xc_domain_setmaxmem(xc->xc_handle, dom, max_memkb) != 0 )
-        return PyErr_SetFromErrno(xc_error);
-    
-    Py_INCREF(zero);
-    return zero;
-}
-
-
-static PyMethodDef pyxc_methods[] = {
-    { "domain_create", 
-      (PyCFunction)pyxc_domain_create, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Create a new domain.\n"
-      " mem_kb [int, 0]:        Memory allocation, in kilobytes.\n"
-      " name   [str, '(anon)']: Informative textual name.\n\n"
-      "Returns: [int] new domain identifier; -1 on error.\n" },
-
-    { "domain_pause", 
-      (PyCFunction)pyxc_domain_pause, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Temporarily pause execution of a domain.\n"
-      " dom [int]: Identifier of domain to be paused.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "domain_unpause", 
-      (PyCFunction)pyxc_domain_unpause, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "(Re)start execution of a domain.\n"
-      " dom [int]: Identifier of domain to be unpaused.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "domain_destroy", 
-      (PyCFunction)pyxc_domain_destroy, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Destroy a domain.\n"
-      " dom [int]:    Identifier of domain to be destroyed.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "domain_pincpu", 
-      (PyCFunction)pyxc_domain_pincpu, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Pin a domain to a specified CPU.\n"
-      " dom [int]:     Identifier of domain to be pinned.\n"
-      " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "domain_getinfo", 
-      (PyCFunction)pyxc_domain_getinfo, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Get information regarding a set of domains, in increasing id order.\n"
-      " first_dom [int, 0]:    First domain to retrieve info about.\n"
-      " max_doms  [int, 1024]: Maximum number of domains to retrieve info"
-      " about.\n\n"
-      "Returns: [list of dicts] if list length is less than 'max_doms'\n"
-      "         parameter then there was an error, or the end of the\n"
-      "         domain-id space was reached.\n"
-      " dom      [int]: Identifier of domain to which this info pertains\n"
-      " cpu      [int]:  CPU to which this domain is bound\n"
-      " dying    [int]:  Bool - is the domain dying?\n"
-      " crashed  [int]:  Bool - has the domain crashed?\n"
-      " shutdown [int]:  Bool - has the domain shut itself down?\n"
-      " paused   [int]:  Bool - is the domain paused by control software?\n"
-      " blocked  [int]:  Bool - is the domain blocked waiting for an event?\n"
-      " running  [int]:  Bool - is the domain currently running?\n"
-      " mem_kb   [int]:  Memory reservation, in kilobytes\n"
-      " cpu_time [long]: CPU time consumed, in nanoseconds\n"
-      " name     [str]:  Identifying name\n"
-      " shutdown_reason [int]: Numeric code from guest OS, explaining "
-      "reason why it shut itself down.\n" },
-
-    { "linux_save", 
-      (PyCFunction)pyxc_linux_save, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Save the CPU and memory state of a Linux guest OS.\n"
-      " dom        [int]:    Identifier of domain to be saved.\n"
-      " state_file [str]:    Name of state file. Must not currently exist.\n"
-      " progress   [int, 1]: Bool - display a running progress indication?\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "linux_restore", 
-      (PyCFunction)pyxc_linux_restore, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Restore the CPU and memory state of a Linux guest OS.\n"
-      " state_file [str]:    Name of state file. Must not currently exist.\n"
-      " progress   [int, 1]: Bool - display a running progress indication?\n\n"
-      "Returns: [int] new domain identifier on success; -1 on error.\n" },
-
-    { "linux_build", 
-      (PyCFunction)pyxc_linux_build, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Build a new Linux guest OS.\n"
-      " dom     [int]:      Identifier of domain to build into.\n"
-      " image   [str]:      Name of kernel image file. May be gzipped.\n"
-      " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
-      " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "netbsd_build", 
-      (PyCFunction)pyxc_netbsd_build, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Build a new NetBSD guest OS.\n"
-      " dom     [int]:     Identifier of domain to build into.\n"
-      " image   [str]:      Name of kernel image file. May be gzipped.\n"
-      " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "bvtsched_global_set",
-      (PyCFunction)pyxc_bvtsched_global_set,
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
-      " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "bvtsched_global_get",
-      (PyCFunction)pyxc_bvtsched_global_get,
-      METH_KEYWORDS, "\n"
-      "Get global tuning parameters for BVT scheduler.\n"
-      "Returns: [dict]:\n"
-      " ctx_allow [int]: context switch allowance\n" },
-
-    { "bvtsched_domain_set",
-      (PyCFunction)pyxc_bvtsched_domain_set,
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
-      " dom    [int]: Identifier of domain to be tuned.\n"
-      " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
-      " warp   [int]: How far to warp domain's EVT on unblock.\n"
-      " warpl  [int]: How long the domain can run warped.\n"
-      " warpu  [int]: How long before the domain can warp again.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "bvtsched_domain_get",
-      (PyCFunction)pyxc_bvtsched_domain_get,
-      METH_KEYWORDS, "\n"
-      "Get per-domain tuning parameters under the BVT scheduler.\n"
-      " dom [int]: Identifier of domain to be queried.\n"
-      "Returns [dict]:\n"
-      " domain [int]:  Domain ID.\n"
-      " mcuadv [long]: MCU Advance.\n"
-      " warp   [long]: Warp.\n"
-      " warpu  [long]: Unwarp requirement.\n"
-      " warpl  [long]: Warp limit,\n"
-    },
-
-    { "atropos_domain_set",
-      (PyCFunction)pyxc_atropos_domain_set,
-      METH_KEYWORDS, "\n"
-      "Set the scheduling parameters for a domain when running with Atropos.\n"
-      " dom      [int]:  domain to set\n"
-      " period   [long]: domain's scheduling period\n"
-      " slice    [long]: domain's slice per period\n"
-      " latency  [long]: wakeup latency hint\n"
-      " xtratime [int]: boolean\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "atropos_domain_get",
-      (PyCFunction)pyxc_atropos_domain_get,
-      METH_KEYWORDS, "\n"
-      "Get the current scheduling parameters for a domain when running with\n"
-      "the Atropos scheduler."
-      " dom      [int]: domain to query\n"
-      "Returns:  [dict]\n"
-      " domain   [int]: domain ID\n"
-      " period   [long]: scheduler period\n"
-      " slice    [long]: CPU reservation per period\n"
-      " latency  [long]: unblocking latency hint\n"
-      " xtratime [int] : 0 if not using slack time, nonzero otherwise\n" },
-
-    { "rrobin_global_set",
-      (PyCFunction)pyxc_rrobin_global_set,
-      METH_KEYWORDS, "\n"
-      "Set Round Robin scheduler slice.\n"
-      " slice [long]: Round Robin scheduler slice\n"
-      "Returns: [int] 0 on success, throws an exception on failure\n" },
-
-    { "rrobin_global_get",
-      (PyCFunction)pyxc_rrobin_global_get,
-      METH_KEYWORDS, "\n"
-      "Get Round Robin scheduler settings\n"
-      "Returns [dict]:\n"
-      " slice  [long]: Scheduler time slice.\n" },    
-
-    { "evtchn_bind_interdomain", 
-      (PyCFunction)pyxc_evtchn_bind_interdomain, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Open an event channel between two domains.\n"
-      " dom1 [int, SELF]: First domain to be connected.\n"
-      " dom2 [int, SELF]: Second domain to be connected.\n\n"
-      "Returns: [dict] dictionary is empty on failure.\n"
-      " port1 [int]: Port-id for endpoint at dom1.\n"
-      " port2 [int]: Port-id for endpoint at dom2.\n" },
-
-    { "evtchn_bind_virq", 
-      (PyCFunction)pyxc_evtchn_bind_virq, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Bind an event channel to the specified VIRQ.\n"
-      " virq [int]: VIRQ to bind.\n\n"
-      "Returns: [int] Bound event-channel port.\n" },
-
-    { "evtchn_close", 
-      (PyCFunction)pyxc_evtchn_close, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Close an event channel.\n"
-      " dom  [int, SELF]: Dom-id of one endpoint of the channel.\n"
-      " port [int]:       Port-id of one endpoint of the channel.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "evtchn_send", 
-      (PyCFunction)pyxc_evtchn_send, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Send an event along a locally-connected event channel.\n"
-      " port [int]: Port-id of a local channel endpoint.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "evtchn_status", 
-      (PyCFunction)pyxc_evtchn_status, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Query the status of an event channel.\n"
-      " dom  [int, SELF]: Dom-id of one endpoint of the channel.\n"
-      " port [int]:       Port-id of one endpoint of the channel.\n\n"
-      "Returns: [dict] dictionary is empty on failure.\n"
-      " status [str]:  'closed', 'unbound', 'interdomain', 'pirq',"
-      " or 'virq'.\n"
-      "The following are returned if 'status' is 'interdomain':\n"
-      " dom  [int]: Dom-id of remote endpoint.\n"
-      " port [int]: Port-id of remote endpoint.\n"
-      "The following are returned if 'status' is 'pirq' or 'virq':\n"
-      " irq  [int]: IRQ number.\n" },
-
-    { "physdev_pci_access_modify",
-      (PyCFunction)pyxc_physdev_pci_access_modify,
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Allow a domain access to a PCI device\n"
-      " dom    [int]: Identifier of domain to be allowed access.\n"
-      " bus    [int]: PCI bus\n"
-      " dev    [int]: PCI slot\n"
-      " func   [int]: PCI function\n"
-      " enable [int]: Non-zero means enable access; else disable access\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-    { "readconsolering", 
-      (PyCFunction)pyxc_readconsolering, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Read Xen's console ring.\n"
-      " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
-      "Returns: [str] string is empty on failure.\n" },
-
-    { "physinfo",
-      (PyCFunction)pyxc_physinfo,
-      METH_VARARGS, "\n"
-      "Get information about the physical host machine\n"
-      "Returns [dict]: information about the hardware"
-      "        [None]: on failure.\n" },
-
-    { "shadow_control", 
-      (PyCFunction)pyxc_shadow_control, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Set parameter for shadow pagetable interface\n"
-      " dom [int]:   Identifier of domain.\n"
-      " op [int, 0]: operation\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "domain_setname", 
-      (PyCFunction)pyxc_domain_setname, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Set domain informative textual name\n"
-      " dom [int]:  Identifier of domain.\n"
-      " name [str]: Text string.\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { "domain_setmaxmem", 
-      (PyCFunction)pyxc_domain_setname, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Set a domain's memory limit\n"
-      " dom [int]: Identifier of domain.\n"
-      " max_memkb [long]: .\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-
-/*
- * Definitions for the 'Xc' module wrapper.
- */
-
-staticforward PyTypeObject PyXcType;
-
-static PyObject *PyXc_new(PyObject *self, PyObject *args)
-{
-    XcObject *xc;
-
-    if ( !PyArg_ParseTuple(args, ":new") )
-        return NULL;
-
-    xc = PyObject_New(XcObject, &PyXcType);
-
-    if ( (xc->xc_handle = xc_interface_open()) == -1 )
-    {
-        PyObject_Del((PyObject *)xc);
-        return PyErr_SetFromErrno(xc_error);
-    }
-
-    return (PyObject *)xc;
-}
-
-static PyObject *PyXc_getattr(PyObject *obj, char *name)
-{
-    return Py_FindMethod(pyxc_methods, obj, name);
-}
-
-static void PyXc_dealloc(PyObject *self)
-{
-    XcObject *xc = (XcObject *)self;
-    (void)xc_interface_close(xc->xc_handle);
-    PyObject_Del(self);
-}
-
-static PyTypeObject PyXcType = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "Xc",
-    sizeof(XcObject),
-    0,
-    PyXc_dealloc,    /* tp_dealloc     */
-    NULL,            /* tp_print       */
-    PyXc_getattr,    /* tp_getattr     */
-    NULL,            /* tp_setattr     */
-    NULL,            /* tp_compare     */
-    NULL,            /* tp_repr        */
-    NULL,            /* tp_as_number   */
-    NULL,            /* tp_as_sequence */
-    NULL,            /* tp_as_mapping  */
-    NULL             /* tp_hash        */
-};
-
-static PyMethodDef PyXc_methods[] = {
-    { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
-    { NULL, NULL, 0, NULL }
-};
-
-PyMODINIT_FUNC initxc(void)
-{
-    PyObject *m, *d;
-
-    m = Py_InitModule(XENPKG, PyXc_methods);
-
-    d = PyModule_GetDict(m);
-    xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
-    PyDict_SetItemString(d, "error", xc_error);
-
-    zero = PyInt_FromLong(0);
-}
diff --git a/tools/xc/py/setup.py b/tools/xc/py/setup.py
deleted file mode 100644 (file)
index 8efe5ca..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-
-from distutils.core import setup, Extension
-
-module = Extension("xc",
-                   extra_compile_args   = ["-fno-strict-aliasing"],
-                   include_dirs         = ["../lib",
-                                           "../../../xen/include/hypervisor-ifs",
-                                           "../../../linux-xen-sparse/include",
-                                           "../../xu/lib",
-                                           "../../lib" ],
-                   library_dirs         = ["../lib",
-                                           "../../lib" ],
-                   libraries            = ["xc"],
-                   sources              = ["Xc.c"])
-
-setup(name = "xc",
-      version = "2.0",
-      ext_package = "xen.ext",
-      ext_modules = [module])
diff --git a/tools/xen/Makefile b/tools/xen/Makefile
deleted file mode 100644 (file)
index 343a596..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-
-all:
-       python setup.py build
-
-install: all
-       if [ "$(prefix)" = "" ]; then                   \
-           python setup.py install;                    \
-       elif [ "$(dist)" = "yes" ]; then                \
-           python setup.py install --home="$(prefix)"; \
-       else                                            \
-           python setup.py install --root="$(prefix)"; \
-       fi
-       mkdir -p $(prefix)/usr/sbin
-       install -m0755 xend $(prefix)/usr/sbin
-       install -m0755 xm $(prefix)/usr/sbin
-       mkdir -p $(prefix)/etc/xen/xend
-       install -m0755 vifctl $(prefix)/etc/xen/xend
-
-clean:
-       rm -rf build *.pyc *.pyo *.o *.a *~
diff --git a/tools/xen/lib/__init__.py b/tools/xen/lib/__init__.py
deleted file mode 100644 (file)
index 8d1c8b6..0000000
+++ /dev/null
@@ -1 +0,0 @@
diff --git a/tools/xen/lib/ext/__init__.py b/tools/xen/lib/ext/__init__.py
deleted file mode 100644 (file)
index 8d1c8b6..0000000
+++ /dev/null
@@ -1 +0,0 @@
diff --git a/tools/xen/lib/util/Brctl.py b/tools/xen/lib/util/Brctl.py
deleted file mode 100644 (file)
index 9d3eba1..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-"""Bridge control utilities.
-"""
-import os
-import os.path
-import re
-import sys
-
-os.defpath = os.defpath + ':/sbin:/usr/sbin:/usr/local/sbin'
-CMD_IFCONFIG = 'ifconfig'
-CMD_ROUTE    = 'route'
-CMD_BRCTL    = 'brctl'
-CMD_IPTABLES = "iptables"
-
-opts = None
-
-class Opts:
-
-    def __init__(self, defaults):
-        for (k, v) in defaults.items():
-            setattr(self, k, v)
-        pass
-
-def cmd(p, s):
-    """Print and execute command 'p' with args 's'.
-    """
-    global opts
-    c = p + ' ' + s
-    if opts.verbose: print c
-    if not opts.dryrun:
-        os.system(c)
-
-def vif_bridge_add(params):
-    """Add the network interface for vif on dom to a bridge.
-    """
-    cmd(CMD_BRCTL, 'addif %(bridge)s %(vif)s' % params)
-
-def vif_bridge_rem(params):
-    """Remove the network interface for vif on dom from a bridge.
-    """
-    cmd(CMD_BRCTL, 'delif %(bridge)s %(vif)s' % params)
-
-def vif_restrict_addr(vif, addr, delete=0):
-    d = { 'vif': vif, 'addr': addr}
-    if delete:
-        d['flag'] = '-D'
-    else:
-        d['flag'] = '-A'
-    cmd(CMD_IPTABLES, '-P FORWARD DROP')
-    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-in %(vif)s -s %(addr)s -j ACCEPT' % d)
-    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-out %(vif)s -d %(addr)s -j ACCEPT' % d)
-
-def bridge_create(bridge, **kwd):
-    """Create a bridge.
-    Defaults hello time to 0, forward delay to 0 and stp off.
-    """
-    cmd(CMD_BRCTL, 'addbr %s' % bridge)
-    if kwd.get('hello', None) is None:
-        kwd['hello'] = 0
-    if kwd.get('fd', None) is None:
-        kwd['fd'] = 0
-    if kwd.get('stp', None) is None:
-        kwd['stp'] = 'off'
-    bridge_set(bridge, **kwd)
-
-def bridge_set(bridge, hello=None, fd=None, stp=None):
-    """Set bridge parameters.
-    """
-    if hello is not None:
-        cmd(CMD_BRCTL, 'sethello %s %d' % (bridge, hello))
-    if fd is not None:
-        cmd(CMD_BRCTL, 'setfd %s %d' % (bridge, fd))
-    if stp is not None:
-        cmd(CMD_BRCTL, 'stp %s %s' % (bridge, stp))
-
-def bridge_del(bridge):
-    """Delete a bridge.
-    """
-    cmd(CMD_BRCTL, 'delbr %s' % bridge)
-
-def routes():
-    """Return a list of the routes.
-    """
-    fin = os.popen(CMD_ROUTE + ' -n', 'r')
-    routes = []
-    for x in fin:
-        if x.startswith('Kernel'): continue
-        if x.startswith('Destination'): continue
-        x = x.strip()
-        y = x.split()
-        z = { 'destination': y[0],
-              'gateway'    : y[1],
-              'mask'       : y[2],
-              'flags'      : y[3],
-              'metric'     : y[4],
-              'ref'        : y[5],
-              'use'        : y[6],
-              'interface'  : y[7] }
-        routes.append(z)
-    return routes
-
-def ifconfig(interface):
-    """Return the ip config for an interface,
-    """
-    fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r')
-    inetre = re.compile('\s*inet\s*addr:(?P<address>\S*)\s*Bcast:(?P<broadcast>\S*)\s*Mask:(?P<mask>\S*)')
-    info = None
-    for x in fin:
-        m = inetre.match(x)
-        if not m: continue
-        info = m.groupdict()
-        info['interface'] = interface
-        break
-    return info
-
-def reconfigure(interface, bridge):
-    """Reconfigure an interface to be attached to a bridge, and give the bridge
-    the IP address etc. from interface. Move the default route to the interface
-    to the bridge.
-
-    """
-    global opts
-    intf_info = ifconfig(interface)
-    if not intf_info:
-        print >>sys.stderr, 'Interface not found:', interface
-        return
-    #bridge_info = ifconfig(bridge)
-    #if not bridge_info:
-    #    print >>sys.stderr, 'Bridge not found:', bridge
-    #    return
-    route_info = routes()
-    intf_info['bridge'] = bridge
-    intf_info['gateway'] = None
-    for r in route_info:
-        if (r['destination'] == '0.0.0.0' and
-            'G' in r['flags'] and
-            r['interface'] == interface):
-            intf_info['gateway'] = r['gateway']
-    if not intf_info['gateway']:
-        print >>sys.stderr, 'Gateway not found: ', interface
-        return
-    cmd(CMD_IFCONFIG,
-        '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up'
-        % intf_info)
-    cmd(CMD_ROUTE,
-        'add default gateway %(gateway)s dev %(bridge)s'
-        % intf_info)
-    cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info)
-    cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info)
-
-defaults = {
-    'verbose'  : 1,
-    'dryrun'   : 0,
-    }
-
-opts = Opts(defaults)
-
-def set_opts(val):
-    global opts
-    opts = val
-    return opts
diff --git a/tools/xen/lib/util/__init__.py b/tools/xen/lib/util/__init__.py
deleted file mode 100644 (file)
index 8d1c8b6..0000000
+++ /dev/null
@@ -1 +0,0 @@
diff --git a/tools/xen/lib/util/console_client.py b/tools/xen/lib/util/console_client.py
deleted file mode 100644 (file)
index 7ac63ae..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-
-##############################################
-# Console client for Xen guest OSes
-# Copyright (c) 2004, K A Fraser
-##############################################
-
-import errno, os, signal, socket, struct, sys
-
-from termios import *
-# Indexes into termios.tcgetattr() list.
-IFLAG  = 0
-OFLAG  = 1
-CFLAG  = 2
-LFLAG  = 3
-ISPEED = 4
-OSPEED = 5
-CC     = 6
-
-def __child_death(signum, frame):
-    global stop
-    stop = True
-
-def __recv_from_sock(sock):
-    global stop
-    stop = False
-    while not stop:
-        try:
-            data = sock.recv(1024)
-            os.write(1, data)
-        except socket.error, error:
-            if error[0] != errno.EINTR:
-                raise
-    os.wait()
-
-def __send_to_sock(sock):
-    while 1:
-        data = os.read(0,1024)
-        if ord(data[0]) == ord(']')-64:
-            break
-        try:
-            sock.send(data)
-        except socket.error, error:
-            if error[0] == errno.EPIPE:
-                sys.exit(0)
-            if error[0] != errno.EINTR:
-                raise
-    sys.exit(0)
-
-def connect(host,port):
-    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
-    sock.connect((host,port))
-
-    oattrs = tcgetattr(0)
-    nattrs = tcgetattr(0)
-    nattrs[IFLAG] = nattrs[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
-    nattrs[OFLAG] = nattrs[OFLAG] & ~(OPOST)
-    nattrs[CFLAG] = nattrs[CFLAG] & ~(CSIZE | PARENB)
-    nattrs[CFLAG] = nattrs[CFLAG] | CS8
-    nattrs[LFLAG] = nattrs[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
-    nattrs[CC][VMIN] = 1
-    nattrs[CC][VTIME] = 0
-
-    if os.fork():
-        signal.signal(signal.SIGCHLD, __child_death)
-        print "************ REMOTE CONSOLE: CTRL-] TO QUIT ********"
-        tcsetattr(0, TCSAFLUSH, nattrs)
-        try:
-            __recv_from_sock(sock)
-        finally:
-            tcsetattr(0, TCSAFLUSH, oattrs)
-            print
-            print "************ REMOTE CONSOLE EXITED *****************"
-    else:
-        signal.signal(signal.SIGPIPE, signal.SIG_IGN)
-        __send_to_sock(sock)
-
-if __name__ == '__main__':
-    if len(sys.argv) != 3:
-        print sys.argv[0] + " <host> <port>"
-        sys.exit(1)
-    connect(str(sys.argv[1]),int(sys.argv[2]))
diff --git a/tools/xen/lib/util/ip.py b/tools/xen/lib/util/ip.py
deleted file mode 100644 (file)
index 8396e0d..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-import os
-import re
-import socket
-import struct
-
-def readlines(fd):
-    """Version of readlines safe against EINTR.
-    """
-    import errno
-    
-    lines = []
-    while 1:
-        try:
-            line = fd.readline()
-        except IOError, ex:
-            if ex.errno == errno.EINTR:
-                continue
-            else:
-                raise
-        if line == '': break
-        lines.append(line)
-    return lines
-
-def readline(fd):
-    """Version of readline safe against EINTR.
-    """
-    while 1:
-        try:
-            return fd.readline()
-        except IOError, ex:
-            if ex.errno == errno.EINTR:
-                continue
-            else:
-                raise
-
-##### Networking-related functions
-
-"""Bridge for network backend.
-When bridging is used, eth0 may not have an IP address,
-as it may have been moved onto the bridge.
-"""
-NBE_BRIDGE = 'nbe-br'
-
-def get_current_ipaddr(dev='eth0'):
-    """Return a string containing the primary IP address for the given
-    network interface (default 'eth0').
-    """
-    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
-    lines = readlines(fd)
-    for line in lines:
-        m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
-                       line )
-        if m:
-            return m.group(1)
-    if dev == 'eth0':
-        return get_current_ipaddr(NBE_BRIDGE)
-    return None
-
-def get_current_ipmask(dev='eth0'):
-    """Return a string containing the primary IP netmask for the given
-    network interface (default 'eth0').
-    """
-    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
-    lines = readlines(fd)
-    for line in lines:
-        m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
-                       line )
-        if m:
-            return m.group(1)
-    if dev == 'eth0':
-        return get_current_ipmask(NBE_BRIDGE)
-    return None
-
-def get_current_ipgw(dev='eth0'):
-    """Return a string containing the IP gateway for the given
-    network interface (default 'eth0').
-    """
-    fd = os.popen( '/sbin/route -n' )
-    lines = readlines(fd)
-    for line in lines:
-        m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
-                       '\s+\S+\s+\S*G.*' + dev + '.*', line )
-        if m:
-            return m.group(1)
-    if dev == 'eth0':
-        return get_current_ipgw(NBE_BRIDGE)
-    return None
-
-def inet_aton(addr):
-    """Convert an IP addr in IPv4 dot notation into an int.
-    """
-    b = socket.inet_aton(addr)
-    return struct.unpack('!I', b)[0]
-
-def inet_ntoa(n):
-    """Convert an int into an IP addr in IPv4 dot notation.
-    """
-    b = struct.pack('!I', n)
-    return socket.inet_ntoa(b)
-
-def add_offset_to_ip(addr, offset):
-    """Add a numerical offset to an IP addr in IPv4 dot notation.
-    """
-    n = inet_aton(addr)
-    n += offset
-    return inet_ntoa(n)
-
-def check_subnet( ip, network, netmask ):
-    n_ip = inet_aton(ip)
-    n_net = inet_aton(network)
-    n_mask = inet_aton(netmask)
-    return (n_ip & n_mask) == (n_net & n_mask)
-
diff --git a/tools/xen/lib/util/tempfile.py b/tools/xen/lib/util/tempfile.py
deleted file mode 100644 (file)
index 756d8c8..0000000
+++ /dev/null
@@ -1,451 +0,0 @@
-"""Temporary files.
-
-This module provides generic, low- and high-level interfaces for
-creating temporary files and directories.  The interfaces listed
-as "safe" just below can be used without fear of race conditions.
-Those listed as "unsafe" cannot, and are provided for backward
-compatibility only.
-
-This module also provides some data items to the user:
-
-  TMP_MAX  - maximum number of names that will be tried before
-             giving up.
-  template - the default prefix for all temporary names.
-             You may change this to control the default prefix.
-  tempdir  - If this is set to a string before the first use of
-             any routine from this module, it will be considered as
-             another candidate location to store temporary files.
-"""
-
-__all__ = [
-    "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
-    "mkstemp", "mkdtemp",                  # low level safe interfaces
-    "mktemp",                              # deprecated unsafe interface
-    "TMP_MAX", "gettempprefix",            # constants
-    "tempdir", "gettempdir"
-   ]
-
-
-# Imports.
-
-import os as _os
-import errno as _errno
-from random import Random as _Random
-
-if _os.name == 'mac':
-    import Carbon.Folder as _Folder
-    import Carbon.Folders as _Folders
-
-try:
-    import fcntl as _fcntl
-    # If PYTHONCASEOK is set on Windows, stinking FCNTL.py gets
-    # imported, and we don't get an ImportError then.  Provoke
-    # an AttributeError instead in that case.
-    _fcntl.fcntl
-except (ImportError, AttributeError):
-    def _set_cloexec(fd):
-        pass
-else:
-    def _set_cloexec(fd):
-        flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
-        if flags >= 0:
-            # flags read successfully, modify
-            flags |= _fcntl.FD_CLOEXEC
-            _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
-
-
-try:
-    import thread as _thread
-except ImportError:
-    import dummy_thread as _thread
-_allocate_lock = _thread.allocate_lock
-
-_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
-if hasattr(_os, 'O_NOINHERIT'):
-    _text_openflags |= _os.O_NOINHERIT
-if hasattr(_os, 'O_NOFOLLOW'):
-    _text_openflags |= _os.O_NOFOLLOW
-
-_bin_openflags = _text_openflags
-if hasattr(_os, 'O_BINARY'):
-    _bin_openflags |= _os.O_BINARY
-
-if hasattr(_os, 'TMP_MAX'):
-    TMP_MAX = _os.TMP_MAX
-else:
-    TMP_MAX = 10000
-
-template = "tmp"
-
-tempdir = None
-
-# Internal routines.
-
-_once_lock = _allocate_lock()
-
-class _RandomNameSequence:
-    """An instance of _RandomNameSequence generates an endless
-    sequence of unpredictable strings which can safely be incorporated
-    into file names.  Each string is six characters long.  Multiple
-    threads can safely use the same instance at the same time.
-
-    _RandomNameSequence is an iterator."""
-
-    characters = ("abcdefghijklmnopqrstuvwxyz" +
-                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
-                  "0123456789-_")
-
-    def __init__(self):
-        self.mutex = _allocate_lock()
-        self.rng = _Random()
-        self.normcase = _os.path.normcase
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        m = self.mutex
-        c = self.characters
-        choose = self.rng.choice
-
-        m.acquire()
-        try:
-            letters = [choose(c) for dummy in "123456"]
-        finally:
-            m.release()
-
-        return self.normcase(''.join(letters))
-
-def _candidate_tempdir_list():
-    """Generate a list of candidate temporary directories which
-    _get_default_tempdir will try."""
-
-    dirlist = []
-
-    # First, try the environment.
-    for envname in 'TMPDIR', 'TEMP', 'TMP':
-        dirname = _os.getenv(envname)
-        if dirname: dirlist.append(dirname)
-
-    # Failing that, try OS-specific locations.
-    if _os.name == 'mac':
-        try:
-            fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
-                                              _Folders.kTemporaryFolderType, 1)
-            dirname = fsr.as_pathname()
-            dirlist.append(dirname)
-        except _Folder.error:
-            pass
-    elif _os.name == 'riscos':
-        dirname = _os.getenv('Wimp$ScrapDir')
-        if dirname: dirlist.append(dirname)
-    elif _os.name == 'nt':
-        dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
-    else:
-        dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
-
-    # As a last resort, the current directory.
-    try:
-        dirlist.append(_os.getcwd())
-    except (AttributeError, _os.error):
-        dirlist.append(_os.curdir)
-
-    return dirlist
-
-def _get_default_tempdir():
-    """Calculate the default directory to use for temporary files.
-    This routine should be called exactly once.
-
-    We determine whether or not a candidate temp dir is usable by
-    trying to create and write to a file in that directory.  If this
-    is successful, the test file is deleted.  To prevent denial of
-    service, the name of the test file must be randomized."""
-
-    namer = _RandomNameSequence()
-    dirlist = _candidate_tempdir_list()
-    flags = _text_openflags
-
-    for dir in dirlist:
-        if dir != _os.curdir:
-            dir = _os.path.normcase(_os.path.abspath(dir))
-        # Try only a few names per directory.
-        for seq in xrange(100):
-            name = namer.next()
-            filename = _os.path.join(dir, name)
-            try:
-                fd = _os.open(filename, flags, 0600)
-                fp = _os.fdopen(fd, 'w')
-                fp.write('blat')
-                fp.close()
-                _os.unlink(filename)
-                del fp, fd
-                return dir
-            except (OSError, IOError), e:
-                if e[0] != _errno.EEXIST:
-                    break # no point trying more names in this directory
-                pass
-    raise IOError, (_errno.ENOENT,
-                    ("No usable temporary directory found in %s" % dirlist))
-
-_name_sequence = None
-
-def _get_candidate_names():
-    """Common setup sequence for all user-callable interfaces."""
-
-    global _name_sequence
-    if _name_sequence is None:
-        _once_lock.acquire()
-        try:
-            if _name_sequence is None:
-                _name_sequence = _RandomNameSequence()
-        finally:
-            _once_lock.release()
-    return _name_sequence
-
-
-def _mkstemp_inner(dir, pre, suf, flags):
-    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
-
-    names = _get_candidate_names()
-
-    for seq in xrange(TMP_MAX):
-        name = names.next()
-        file = _os.path.join(dir, pre + name + suf)
-        try:
-            fd = _os.open(file, flags, 0600)
-            _set_cloexec(fd)
-            return (fd, file)
-        except OSError, e:
-            if e.errno == _errno.EEXIST:
-                continue # try again
-            raise
-
-    raise IOError, (_errno.EEXIST, "No usable temporary file name found")
-
-
-# User visible interfaces.
-
-def gettempprefix():
-    """Accessor for tempdir.template."""
-    return template
-
-tempdir = None
-
-def gettempdir():
-    """Accessor for tempdir.tempdir."""
-    global tempdir
-    if tempdir is None:
-        _once_lock.acquire()
-        try:
-            if tempdir is None:
-                tempdir = _get_default_tempdir()
-        finally:
-            _once_lock.release()
-    return tempdir
-
-def mkstemp(suffix="", prefix=template, dir=None, text=False):
-    """mkstemp([suffix, [prefix, [dir, [text]]]])
-    User-callable function to create and return a unique temporary
-    file.  The return value is a pair (fd, name) where fd is the
-    file descriptor returned by os.open, and name is the filename.
-
-    If 'suffix' is specified, the file name will end with that suffix,
-    otherwise there will be no suffix.
-
-    If 'prefix' is specified, the file name will begin with that prefix,
-    otherwise a default prefix is used.
-
-    If 'dir' is specified, the file will be created in that directory,
-    otherwise a default directory is used.
-
-    If 'text' is specified and true, the file is opened in text
-    mode.  Else (the default) the file is opened in binary mode.  On
-    some operating systems, this makes no difference.
-
-    The file is readable and writable only by the creating user ID.
-    If the operating system uses permission bits to indicate whether a
-    file is executable, the file is executable by no one. The file
-    descriptor is not inherited by children of this process.
-
-    Caller is responsible for deleting the file when done with it.
-    """
-
-    if dir is None:
-        dir = gettempdir()
-
-    if text:
-        flags = _text_openflags
-    else:
-        flags = _bin_openflags
-
-    return _mkstemp_inner(dir, prefix, suffix, flags)
-
-
-def mkdtemp(suffix="", prefix=template, dir=None):
-    """mkdtemp([suffix, [prefix, [dir]]])
-    User-callable function to create and return a unique temporary
-    directory.  The return value is the pathname of the directory.
-
-    Arguments are as for mkstemp, except that the 'text' argument is
-    not accepted.
-
-    The directory is readable, writable, and searchable only by the
-    creating user.
-
-    Caller is responsible for deleting the directory when done with it.
-    """
-
-    if dir is None:
-        dir = gettempdir()
-
-    names = _get_candidate_names()
-
-    for seq in xrange(TMP_MAX):
-        name = names.next()
-        file = _os.path.join(dir, prefix + name + suffix)
-        try:
-            _os.mkdir(file, 0700)
-            return file
-        except OSError, e:
-            if e.errno == _errno.EEXIST:
-                continue # try again
-            raise
-
-    raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
-
-def mktemp(suffix="", prefix=template, dir=None):
-    """mktemp([suffix, [prefix, [dir]]])
-    User-callable function to return a unique temporary file name.  The
-    file is not created.
-
-    Arguments are as for mkstemp, except that the 'text' argument is
-    not accepted.
-
-    This function is unsafe and should not be used.  The file name
-    refers to a file that did not exist at some point, but by the time
-    you get around to creating it, someone else may have beaten you to
-    the punch.
-    """
-
-##    from warnings import warn as _warn
-##    _warn("mktemp is a potential security risk to your program",
-##          RuntimeWarning, stacklevel=2)
-
-    if dir is None:
-        dir = gettempdir()
-
-    names = _get_candidate_names()
-    for seq in xrange(TMP_MAX):
-        name = names.next()
-        file = _os.path.join(dir, prefix + name + suffix)
-        if not _os.path.exists(file):
-            return file
-
-    raise IOError, (_errno.EEXIST, "No usable temporary filename found")
-
-class _TemporaryFileWrapper:
-    """Temporary file wrapper
-
-    This class provides a wrapper around files opened for
-    temporary use.  In particular, it seeks to automatically
-    remove the file when it is no longer needed.
-    """
-
-    def __init__(self, file, name):
-        self.file = file
-        self.name = name
-        self.close_called = False
-
-    def __getattr__(self, name):
-        file = self.__dict__['file']
-        a = getattr(file, name)
-        if type(a) != type(0):
-            setattr(self, name, a)
-        return a
-
-    # NT provides delete-on-close as a primitive, so we don't need
-    # the wrapper to do anything special.  We still use it so that
-    # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
-    if _os.name != 'nt':
-
-        # Cache the unlinker so we don't get spurious errors at
-        # shutdown when the module-level "os" is None'd out.  Note
-        # that this must be referenced as self.unlink, because the
-        # name TemporaryFileWrapper may also get None'd out before
-        # __del__ is called.
-        unlink = _os.unlink
-
-        def close(self):
-            if not self.close_called:
-                self.close_called = True
-                self.file.close()
-                self.unlink(self.name)
-
-        def __del__(self):
-            self.close()
-
-def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
-                       prefix=template, dir=None):
-    """Create and return a temporary file.
-    Arguments:
-    'prefix', 'suffix', 'dir' -- as for mkstemp.
-    'mode' -- the mode argument to os.fdopen (default "w+b").
-    'bufsize' -- the buffer size argument to os.fdopen (default -1).
-    The file is created as mkstemp() would do it.
-
-    Returns a file object; the name of the file is accessible as
-    file.name.  The file will be automatically deleted when it is
-    closed.
-    """
-
-    if dir is None:
-        dir = gettempdir()
-
-    if 'b' in mode:
-        flags = _bin_openflags
-    else:
-        flags = _text_openflags
-
-    # Setting O_TEMPORARY in the flags causes the OS to delete
-    # the file when it is closed.  This is only supported by Windows.
-    if _os.name == 'nt':
-        flags |= _os.O_TEMPORARY
-
-    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
-    file = _os.fdopen(fd, mode, bufsize)
-    return _TemporaryFileWrapper(file, name)
-
-if _os.name != 'posix' or _os.sys.platform == 'cygwin':
-    # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
-    # while it is open.
-    TemporaryFile = NamedTemporaryFile
-
-else:
-    def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
-                      prefix=template, dir=None):
-        """Create and return a temporary file.
-        Arguments:
-        'prefix', 'suffix', 'directory' -- as for mkstemp.
-        'mode' -- the mode argument to os.fdopen (default "w+b").
-        'bufsize' -- the buffer size argument to os.fdopen (default -1).
-        The file is created as mkstemp() would do it.
-
-        Returns a file object.  The file has no name, and will cease to
-        exist when it is closed.
-        """
-
-        if dir is None:
-            dir = gettempdir()
-
-        if 'b' in mode:
-            flags = _bin_openflags
-        else:
-            flags = _text_openflags
-
-        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
-        try:
-            _os.unlink(name)
-            return _os.fdopen(fd, mode, bufsize)
-        except:
-            _os.close(fd)
-            raise
diff --git a/tools/xen/lib/xend/Args.py b/tools/xen/lib/xend/Args.py
deleted file mode 100644 (file)
index 527e841..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-import sxp
-
-class ArgError(StandardError):
-    pass
-
-class Args:
-    """Argument encoding support for HTTP.
-    """
-    
-    def __init__(self, paramspec, keyspec):
-        self.arg_ord = []
-        self.arg_dict = {}
-        self.key_ord = []
-        self.key_dict = {}
-        for (name, type) in paramspec:
-                self.arg_ord.append(name)
-                self.arg_dict[name] = type
-        for (name, type) in keyspec:
-                self.key_ord.append(name)
-                self.key_dict[name] = type
-
-    def get_args(self, d, xargs=None):
-        args = {}
-        keys = {}
-        params = []
-        if xargs:
-            self.split_args(xargs, args, keys)
-        self.split_args(d, args, keys)
-        for a in self.arg_ord:
-            if a in args:
-                params.append(args[a])
-            else:
-                raise ArgError('Missing parameter: %s' % a)
-        return (params, keys)
-
-    def split_args(self, d, args, keys):
-        for (k, v) in d.items():
-            if k in self.arg_dict:
-                type = self.arg_dict[k]
-                val = self.coerce(type, v)
-                args[k] = val
-            elif k in self.key_dict:
-                type = self.key_dict[k]
-                val = self.coerce(type, v)
-                keys[k] = val
-            else:
-                raise ArgError('Invalid parameter: %s' % k)
-
-    def get_form_args(self, f, xargs=None):
-        d = {}
-        for (k, v) in f.items():
-            n = len(v)
-            if ((k not in self.arg_dict) and
-                (k not in self.key_dict)):
-                continue
-            if n == 0:
-                continue
-            elif n == 1:
-                d[k] = v[0]
-            else:
-                raise ArgError('Too many values for %s' % k)
-        return self.get_args(d, xargs=xargs)
-
-    def coerce(self, type, v):
-        try:
-            if type == 'int':
-                return int(v)
-            if type == 'str':
-                return str(v)
-            if type == 'sxpr':
-                return self.sxpr(v)
-        except ArgError:
-            raise
-        except StandardError, ex:
-            raise ArgError(str(ex))
-
-    def sxpr(self, v):
-        if instanceof(v, types.ListType):
-            return v
-        if instanceof(v, types.File) or hasattr(v, 'readline'):
-            return sxpr_file(v)
-        if instanceof(v, types.StringType):
-            return sxpr_file(StringIO(v))
-        return str(v)
-
-    def sxpr_file(self, fin):
-        try:
-            vals = sxp.parse(fin)
-        except:
-            raise ArgError('Coercion to sxpr failed')
-        if len(vals) == 1:
-            return vals[0]
-        else:
-            raise ArgError('Too many sxprs')
-
-    def call_with_args(self, fn, args, xargs=None):
-        (params, keys) = self.get_args(args, xargs=xargs)
-        fn(*params, **keys)
-
-    def call_with_form_args(self, fn, fargs, xargs=None):
-        (params, keys) = self.get_form_args(fargs, xargs=xargs)
-        fn(*params, **keys)
-
-class ArgFn(Args):
-    """Represent a remote HTTP operation as a function.
-    Used on the client.
-    """
-
-    def __init__(self, fn, paramspec, keyspec={}):
-        Args.__init__(self, paramspec, keyspec)
-        self.fn = fn
-
-    def __call__(self, fargs, xargs=None):
-        return self.call_with_args(self.fn, fargs, xargs=xargs)
-    
-class FormFn(Args):
-    """Represent an operation as a function over a form.
-    Used in the HTTP server.
-    """
-
-    def __init__(self, fn, paramspec, keyspec={}):
-        Args.__init__(self, paramspec, keyspec)
-        self.fn = fn
-
-    def __call__(self, fargs, xargs=None):
-        return self.call_with_form_args(self.fn, fargs, xargs=xargs)
diff --git a/tools/xen/lib/xend/EventServer.py b/tools/xen/lib/xend/EventServer.py
deleted file mode 100644 (file)
index 20c567a..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Simple publish/subscribe event server.
-
-"""
-import string
-
-from twisted.internet import reactor
-
-# subscribe a.b.c h: map a.b.c -> h
-# subscribe a.b.* h: map a.b.* -> h
-# subscribe a.b.? h: map a.b.? -> h
-#
-# for event a.b.c.d:
-#
-# lookup a.b.c.d, call handlers
-#
-# lookup a.b.c.?, call handlers
-#
-# lookup a.b.c.d.*, call handlers
-# lookup a.b.c.*, call handlers
-# lookup a.b.*, call handlers
-# lookup a.*, call handlers
-# lookup *, call handlers
-
-# a.b.c.d = (a b c d)
-# a.b.c.? = (a b c _)
-# a.b.c.* = (a b c . _)
-
-class EventServer:
-
-    DOT = '.'
-    QUERY = '?'
-    DOT_QUERY = DOT + QUERY
-    STAR = '*'
-    DOT_STAR = DOT + STAR
-
-    def __init__(self, run=0):
-        self.handlers = {}
-        self.run = run
-        self.queue = []
-
-    def start(self):
-        """Enable event handling. Sends any queued events.
-        """
-        self.run = 1
-        for (e,v) in self.queue:
-            self.inject(e, v)
-        self.queue = []
-
-    def stop(self):
-        """Suspend event handling. Events injected while suspended
-        are queued until we are started again.
-        """
-        self.run = 0
-
-    def subscribe(self, event, handler):
-        """Subscribe to an event. For example 'a.b.c.d'.
-        A subcription like 'a.b.c.?' ending in '?' matches any value
-        for the '?'. A subscription like 'a.b.c.*' ending in '*' matches
-        any event type with the same prefix, 'a.b.c' in this case.
-
-        event  event name
-        handler event handler fn(event, val)
-        """
-        hl = self.handlers.get(event)
-        if hl is None:
-            self.handlers[event] = [handler]
-        else:
-            hl.append(handler)
-
-    def unsubscribe_all(self, event=None):
-        """Unsubscribe all handlers for a given event, or all handlers.
-
-        event  event (optional)
-        """
-        if event == None:
-            self.handlers.clear()
-        elif event in self.handlers:
-            del self.handlers[event]
-        
-    def unsubscribe(self, event, handler):
-        """Unsubscribe a given event and handler.
-
-        event  event
-        handler handler
-        """
-        hl = self.handlers.get(event)
-        if hl is None:
-            return
-        if handler in hl:
-            hl.remove(handler)
-
-    def inject(self, event, val, async=1):
-        """Inject an event. Handlers for it are called if running, otherwise
-        it is queued.
-
-        event  event type
-        val    event value
-        """
-        if self.run:
-            if async:
-                reactor.callLater(0, self.call_handlers, event, val)
-            else:
-                self.notify_handlers(event, val)
-        else:
-            self.queue.append( (event, val) )
-
-    def call_handlers(self, event, val):
-        """Internal method to call event handlers.
-        """
-        #print ">event", event, val
-        self.call_event_handlers(event, event, val)
-        self.call_query_handlers(event, val)
-        self.call_star_handlers(event, val)
-
-    def call_event_handlers(self, key, event, val):
-        """Call the handlers for an event.
-        It is safe for handlers to subscribe or unsubscribe.
-
-        key    key for handler list
-        event  event type
-        val    event value
-        """
-        hl = self.handlers.get(key)
-        if hl is None:
-            return
-        # Copy the handler list so that handlers can call
-        # subscribe/unsubscribe safely - python list iteration
-        # is not safe against list modification.
-        for h in hl[:]:
-            try:
-                h(event, val)
-            except:
-                pass
-        
-    def call_query_handlers(self, event, val):
-        """Call regex handlers for events matching 'event' that end in '?'.
-
-        event  event type
-        val    event value
-        """
-        dot_idx = event.rfind(self.DOT)
-        if dot_idx == -1:
-            self.call_event_handlers(self.QUERY, event, val)
-        else:
-            event_query = event[0:dot_idx] + self.DOT_QUERY
-            self.call_event_handlers(event_query, event, val)
-
-    def call_star_handlers(self, event, val):
-        """Call regex handlers for events matching 'event' that end in '*'.
-
-        event  event type
-        val    event value
-        """
-        etype = string.split(event, self.DOT)
-        for i in range(len(etype), 0, -1):
-            event_star = self.DOT.join(etype[0:i]) + self.DOT_STAR
-            self.call_event_handlers(event_star, event, val)
-        self.call_event_handlers(self.STAR, event, val)       
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = EventServer()
-        inst.start()
-    return inst
-
-def main():
-    def sys_star(event, val):
-        print 'sys_star', event, val
-
-    def sys_foo(event, val):
-        print 'sys_foo', event, val
-        s.unsubscribe('sys.foo', sys_foo)
-
-    def sys_foo2(event, val):
-        print 'sys_foo2', event, val
-
-    def sys_bar(event, val):
-        print 'sys_bar', event, val
-
-    def sys_foo_bar(event, val):
-        print 'sys_foo_bar', event, val
-
-    def foo_bar(event, val):
-        print 'foo_bar', event, val
-
-    s = EventServer()
-    s.start()
-    s.subscribe('sys.*', sys_star)
-    s.subscribe('sys.foo', sys_foo)
-    s.subscribe('sys.foo', sys_foo2)
-    s.subscribe('sys.bar', sys_bar)
-    s.subscribe('sys.foo.bar', sys_foo_bar)
-    s.subscribe('foo.bar', foo_bar)
-    s.inject('sys.foo', 'hello')
-    print
-    s.inject('sys.bar', 'hello again')
-    print
-    s.inject('sys.foo.bar', 'hello again')
-    print
-    s.inject('foo.bar', 'hello again')
-    print
-    s.inject('foo', 'hello again')
-    print
-    s.start()
-    s.unsubscribe('sys.*', sys_star)
-    s.unsubscribe_all('sys.*')
-    s.inject('sys.foo', 'hello')
-
-if __name__ == "__main__":
-    main()
-
diff --git a/tools/xen/lib/xend/EventTypes.py b/tools/xen/lib/xend/EventTypes.py
deleted file mode 100644 (file)
index 6350baa..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#   Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-## XEND_DOMAIN_CREATE = "xend.domain.create": dom
-## create: 
-## xend.domain.destroy: dom, reason:died/crashed
-## xend.domain.up ?
-
-## xend.domain.unpause: dom
-## xend.domain.pause: dom
-## xend.domain.shutdown: dom
-## xend.domain.destroy: dom
-
-## xend.domain.migrate.begin: dom, to
-## Begin tells: src host, src domain uri, dst host. Dst id known?
-## err: src host, src domain uri, dst host, dst id if known, status (of domain: ok, dead,...), reason
-## end: src host, src domain uri, dst host, dst uri
-
-## Events for both ends of migrate: for exporter and importer?
-## Include migrate id so can tie together.
-## Have uri /xend/migrate/<id> for migrate info (migrations in progress).
-
-## (xend.domain.migrate.begin (src <host>) (src.domain <id>)
-##                            (dst <host>) (id <migrate id>))
-## xend.domain.migrate.end:
-## (xend.domain.migrate.end (domain <id>) (to <host>)
-
-## xend.node.up:  xend uri
-## xend.node.down: xend uri
-
-## xend.error ?
-
-## format:
-
diff --git a/tools/xen/lib/xend/PrettyPrint.py b/tools/xen/lib/xend/PrettyPrint.py
deleted file mode 100644 (file)
index 9e91b11..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""General pretty-printer, including support for SXP.
-
-"""
-import sys
-import types
-import StringIO
-import sxp
-
-class PrettyItem:
-
-    def __init__(self, width):
-        self.width = width
-
-    def insert(self, block):
-        block.addtoline(self)
-
-    def get_width(self):
-        return self.width
-
-    def output(self, out):
-        print '***PrettyItem>output>', self
-        pass
-
-    def prettyprint(self, out, width):
-        print '***PrettyItem>prettyprint>', self
-        return width
-
-class PrettyString(PrettyItem):
-
-    def __init__(self, x):
-        PrettyItem.__init__(self, len(x))
-        self.value = x
-
-    def output(self, out):
-        out.write(self.value)
-
-    def prettyprint(self, line):
-        line.output(self)
-
-    def show(self, out):
-        print >> out, ("(string (width %d) '%s')" % (self.width, self.value))
-
-class PrettySpace(PrettyItem):
-
-    def output(self, out):
-        out.write(' ' * self.width)
-
-    def prettyprint(self, line):
-        line.output(self)
-
-    def show(self, out):
-        print >> out, ("(space (width %d))" % self.width)
-        
-class PrettyBreak(PrettyItem):
-
-    def __init__(self, width, indent):
-        PrettyItem.__init__(self, width)
-        self.indent = indent
-        self.space = 0
-        self.active = 0
-
-    def output(self, out):
-        out.write(' ' * self.width)
-
-    def prettyprint(self, line):
-        if line.breaks(self.space):
-            self.active = 1
-            line.newline(self.indent)
-        else:
-            line.output(self)
-
-    def show(self, out):
-        print >> out, ("(break (width %d) (indent %d) (space %d) (active %d))"
-                       % (self.width, self.indent, self.space, self.lspace, self.active))
-
-class PrettyNewline(PrettySpace):
-
-    def __init__(self, indent):
-        PrettySpace.__init__(self, indent)
-
-    def insert(self, block):
-        block.newline()
-        block.addtoline(self)
-
-    def output(self, out):
-        out.write(' ' * self.width)
-
-    def prettyprint(self, line):
-        line.newline(0)
-        line.output(self)
-
-    def show(self, out):
-        print >> out, ("(nl (indent %d))" % self.indent)
-
-class PrettyLine(PrettyItem):
-    def __init__(self):
-        PrettyItem.__init__(self, 0)
-        self.content = []
-
-    def write(self, x):
-        self.content.append(x)
-
-    def end(self):
-        width = 0
-        lastwidth = 0
-        lastbreak = None
-        for x in self.content:
-            if isinstance(x, PrettyBreak):
-                if lastbreak:
-                    lastbreak.space = (width - lastwidth)
-                lastbreak = x
-                lastwidth = width
-            width += x.get_width()
-        if lastbreak:
-            lastbreak.space = (width - lastwidth)
-        self.width = width
-    def prettyprint(self, line):
-        for x in self.content:
-            x.prettyprint(line)
-
-    def show(self, out):
-        print >> out, '(LINE (width %d)' % self.width
-        for x in self.content:
-            x.show(out)
-        print >> out, ')'
-
-class PrettyBlock(PrettyItem):
-
-    def __init__(self, all=0, parent=None):
-        self.width = 0
-        self.lines = []
-        self.parent = parent
-        self.indent = 0
-        self.all = all
-        self.broken = 0
-        self.newline()
-
-    def add(self, item):
-        item.insert(self)
-
-    def end(self):
-        self.width = 0
-        for l in self.lines:
-            l.end()
-            if self.width < l.width:
-                self.width = l.width
-
-    def breaks(self, n):
-        return self.all and self.broken
-
-    def newline(self):
-        self.lines.append(PrettyLine())
-
-    def addtoline(self, x):
-        self.lines[-1].write(x)
-
-    def prettyprint(self, line):
-        self.indent = line.used
-        line.block = self
-        if not line.fits(self.width):
-            self.broken = 1
-        for l in self.lines:
-            l.prettyprint(line)
-        line.block = self.parent
-
-    def show(self, out):
-        print >> out, ('(BLOCK (width %d) (indent %d) (all %d) (broken %d)' %
-                       (self.width, self.indent, self.all, self.broken))
-        for l in self.lines:
-            l.show(out)
-        print >> out, ')'
-
-class Line:
-
-    def __init__(self, out, width):
-        self.out = out
-        self.width = width
-        self.used = 0
-        self.space = self.width
-
-    def newline(self, indent):
-        indent += self.block.indent
-        self.out.write('\n')
-        self.out.write(' ' * indent)
-        self.used = indent
-        self.space = self.width - self.used
-
-    def fits(self, n):
-        return self.space - n >= 0
-
-    def breaks(self, n):
-        return self.block.breaks(n) or not self.fits(n)
-
-    def output(self, x):
-        n = x.get_width()
-        self.space -= n
-        self.used += n
-        if self.space < 0:
-            self.space = 0
-        x.output(self.out)
-
-class PrettyPrinter:
-    """A prettyprinter based on what I remember of Derek Oppen's
-    prettyprint algorithm from TOPLAS way back.
-    """
-
-    def __init__(self, width=40):
-        self.width = width
-        self.block = None
-        self.top = None
-
-    def write(self, x):
-        self.block.add(PrettyString(x))
-
-    def add(self, item):
-        self.block.add(item)
-
-    def addbreak(self, width=1, indent=4):
-        self.add(PrettyBreak(width, indent))
-
-    def addspace(self, width=1):
-        self.add(PrettySpace(width))
-
-    def addnl(self, indent=0):
-        self.add(PrettyNewline(indent))
-
-    def begin(self, all=0):
-        block = PrettyBlock(all=all, parent=self.block)
-        self.block = block
-
-    def end(self):
-        self.block.end()
-        if self.block.parent:
-            self.block.parent.add(self.block)
-        else:
-            self.top = self.block
-        self.block = self.block.parent
-
-    def prettyprint(self, out=sys.stdout):
-        line = Line(out, self.width)
-        self.top.prettyprint(line)
-
-class SXPPrettyPrinter(PrettyPrinter):
-    """An SXP prettyprinter.
-    """
-    
-    def pstring(self, x):
-        io = StringIO.StringIO()
-        sxp.show(x, out=io)
-        io.seek(0)
-        val = io.getvalue()
-        io.close()
-        return val
-
-    def pprint(self, l):
-        if isinstance(l, types.ListType):
-            self.begin(all=1)
-            self.write('(')
-            i = 0
-            for x in l:
-                if(i): self.addbreak()
-                self.pprint(x)
-                i += 1
-            self.addbreak(width=0, indent=0)
-            self.write(')')
-            self.end()
-        else:
-            self.write(self.pstring(l))
-
-def prettyprint(sxpr, out=sys.stdout, width=80):
-    """Prettyprint an SXP form.
-
-    sxpr       s-expression
-    out                destination
-    width      maximum output width
-    """
-    if isinstance(sxpr, types.ListType):
-        pp = SXPPrettyPrinter(width=width)
-        pp.pprint(sxpr)
-        pp.prettyprint(out=out)
-    else:
-        sxp.show(sxpr, out=out)
-    print >> out
-
-def main():
-    pin = sxp.Parser()
-    while 1:
-        buf = sys.stdin.read(100)
-        pin.input(buf)
-        if buf == '': break
-    l = pin.get_val()
-    prettyprint(l, width=80)
-
-if __name__ == "__main__":
-    main()
-    
diff --git a/tools/xen/lib/xend/Vifctl.py b/tools/xen/lib/xend/Vifctl.py
deleted file mode 100644 (file)
index 49df8f6..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-import os
-import os.path
-import sys
-
-VIFCTL = '/etc/xen/xend/vifctl'
-
-def init():
-    os.system(VIFCTL + ' init ')
-
-def up(vif, mac=None, bridge=None, ipaddr=[]):
-    args = ['vif=%s' % vif]
-    if mac:
-        args.append('mac=%s' % mac)
-    if bridge:
-        args.append('bridge=%s' % bridge)
-    if ipaddr:
-        args.append('ipaddr=%s' % ','.join(ipaddr))
-    os.system(VIFCTL + ' up ' + ' '.join(args))
-
-def down(vif, mac=None, bridge=None, ipaddr=[]):
-    args = ['vif=%s' % vif]
-    if mac:
-        args.append('mac=%s' % mac)
-    if bridge:
-        args.append('bridge=%s' % bridge)
-    if ipaddr:
-        args.append('ipaddr=%s' % ','.join(ipaddr))
-    os.system(VIFCTL + ' down ' + ' '.join(args))
diff --git a/tools/xen/lib/xend/XendClient.py b/tools/xen/lib/xend/XendClient.py
deleted file mode 100644 (file)
index 13dc3db..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Client API for the HTTP interface on xend.
-Callable as a script - see main().
-"""
-import sys
-import httplib
-import types
-from StringIO import StringIO
-import urlparse
-
-from encode import *
-import sxp
-import PrettyPrint
-
-DEBUG = 0
-
-class Foo(httplib.HTTPResponse):
-
-    def begin(self):
-        fin = self.fp
-        while(1):
-            buf = fin.readline()
-            print "***", buf
-            if buf == '':
-                print
-                sys.exit()
-
-
-def sxprio(sxpr):
-    io = StringIO()
-    sxp.show(sxpr, out=io)
-    print >> io
-    io.seek(0)
-    return io
-
-def fileof(val):
-    """Converter for passing configs.
-    Handles lists, files directly.
-    Assumes a string is a file name and passes its contents.
-    """
-    if isinstance(val, types.ListType):
-        return sxprio(val)
-    if isinstance(val, types.StringType):
-        return file(val)
-    if hasattr(val, 'readlines'):
-        return val
-
-# todo: need to sort of what urls/paths are using for objects.
-# e.g. for domains at the moment return '0'.
-# should probably return abs path w.r.t. server, e.g. /xend/domain/0.
-# As an arg, assume abs path is obj uri, otherwise just id.
-
-# Function to convert to full url: Xend.uri(path), e.g.
-# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
-# And should accept urls for ids?
-
-def urljoin(location, root, prefix='', rest=''):
-    prefix = str(prefix)
-    rest = str(rest)
-    base = 'http://' + location + root + prefix
-    url = urlparse.urljoin(base, rest)
-    return url
-
-def nodeurl(location, root, id=''):
-    return urljoin(location, root, 'node/', id)
-
-def domainurl(location, root, id=''):
-    return urljoin(location, root, 'domain/', id)
-
-def consoleurl(location, root, id=''):
-    return urljoin(location, root, 'console/', id)
-
-def deviceurl(location, root, id=''):
-    return urljoin(location, root, 'device/', id)
-
-def vneturl(location, root, id=''):
-    return urljoin(location, root, 'vnet/', id)
-
-def eventurl(location, root, id=''):
-    return urljoin(location, root, 'event/', id)
-
-def xend_request(url, method, data=None):
-    urlinfo = urlparse.urlparse(url)
-    (uproto, ulocation, upath, uparam, uquery, ufrag) = urlinfo
-    if DEBUG: print url, urlinfo
-    if uproto != 'http':
-        raise StandardError('Invalid protocol: ' + uproto)
-    if DEBUG: print '>xend_request', ulocation, upath, method, data
-    (hdr, args) = encode_data(data)
-    if data and method == 'GET':
-        upath += '?' + args
-        args = None
-    if method == "POST" and upath.endswith('/'):
-        upath = upath[:-1]
-    if DEBUG: print "ulocation=", ulocation, "upath=", upath, "args=", args
-    #hdr['User-Agent'] = 'Mozilla'
-    #hdr['Accept'] = 'text/html,text/plain'
-    conn = httplib.HTTPConnection(ulocation)
-    #conn.response_class = Foo
-    if DEBUG: conn.set_debuglevel(1)
-    conn.request(method, upath, args, hdr)
-    resp = conn.getresponse()
-    if DEBUG: print resp.status, resp.reason
-    if DEBUG: print resp.msg.headers
-    if resp.status in [204, 404]:
-        return None
-    if resp.status not in [200, 201, 202, 203]:
-        raise RuntimeError(resp.reason)
-    pin = sxp.Parser()
-    data = resp.read()
-    if DEBUG: print "***data" , data
-    if DEBUG: print "***"
-    pin.input(data);
-    pin.input_eof()
-    conn.close()
-    val = pin.get_val()
-    #if isinstance(val, types.ListType) and sxp.name(val) == 'val':
-    #    val = val[1]
-    if isinstance(val, types.ListType) and sxp.name(val) == 'err':
-        raise RuntimeError(val[1])
-    if DEBUG: print '**val='; sxp.show(val); print
-    return val
-
-def xend_get(url, args=None):
-    return xend_request(url, "GET", args)
-
-def xend_call(url, data):
-    return xend_request(url, "POST", data)
-
-class Xend:
-
-    SRV_DEFAULT = "localhost:8000"
-    ROOT_DEFAULT = "/xend/"
-
-    def __init__(self, srv=None, root=None):
-        self.bind(srv, root)
-
-    def bind(self, srv=None, root=None):
-        if srv is None: srv = self.SRV_DEFAULT
-        if root is None: root = self.ROOT_DEFAULT
-        if not root.endswith('/'): root += '/'
-        self.location = srv
-        self.root = root
-
-    def nodeurl(self, id=''):
-        return nodeurl(self.location, self.root, id)
-
-    def domainurl(self, id=''):
-        return domainurl(self.location, self.root, id)
-
-    def consoleurl(self, id=''):
-        return consoleurl(self.location, self.root, id)
-
-    def deviceurl(self, id=''):
-        return deviceurl(self.location, self.root, id)
-
-    def vneturl(self, id=''):
-        return vneturl(self.location, self.root, id)
-
-    def eventurl(self, id=''):
-        return eventurl(self.location, self.root, id)
-
-    def xend(self):
-        return xend_get(urljoin(self.location, self.root))
-
-    def xend_node(self):
-        return xend_get(self.nodeurl())
-
-    def xend_node_cpu_rrobin_slice_set(self, slice):
-        return xend_call(self.nodeurl(),
-                         {'op'      : 'cpu_rrobin_slice_set',
-                          'slice'   : slice })
-    
-    def xend_node_cpu_bvt_slice_set(self, slice):
-        return xend_call(self.nodeurl(),
-                         {'op'      : 'cpu_bvt_slice_set',
-                          'slice'   : slice })
-
-    def xend_domains(self):
-        return xend_get(self.domainurl())
-
-    def xend_domain_create(self, conf):
-        return xend_call(self.domainurl(),
-                         {'op'      : 'create',
-                          'config'  : fileof(conf) })
-
-    def xend_domain(self, id):
-        return xend_get(self.domainurl(id))
-
-    def xend_domain_unpause(self, id):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'unpause'})
-
-    def xend_domain_pause(self, id):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'pause'})
-
-    def xend_domain_shutdown(self, id):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'shutdown'})
-
-    def xend_domain_destroy(self, id):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'destroy'})
-
-    def xend_domain_save(self, id, filename):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'save',
-                          'file'    : filename})
-
-    def xend_domain_restore(self, id, filename):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'restore',
-                          'file'    : filename })
-
-    def xend_domain_migrate(self, id, dst):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'migrate',
-                          'destination': dst})
-
-    def xend_domain_pincpu(self, id, cpu):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'pincpu',
-                          'cpu'     : cpu})
-
-    def xend_domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'cpu_bvt_set',
-                          'mcuadv'  : mvuadv,
-                          'warp'    : warp,
-                          'warpl'   : warpl,
-                          'warpu'   : warpu })
-
-    def xend_domain_cpu_atropos_set(self, id, period, slice, latency, xtratime):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'cpu_atropos_set',
-                          'period'  : period,
-                          'slice'   : slice,
-                          'latency' : latency,
-                          'xtratime': xtratime })
-
-    def xend_domain_vifs(self, id):
-        return xend_get(self.domainurl(id),
-                        { 'op'      : 'vifs' })
-    
-    def xend_domain_vif_ip_add(self, id, vif, ipaddr):
-        return xend_call(self.domainurl(id),
-                         {'op'      : 'vif_ip_add',
-                          'vif'     : vif,
-                          'ip'      : ipaddr })
-        
-    def xend_domain_vbds(self, id):
-        return xend_get(self.domainurl(id),
-                        {'op'       : 'vbds'})
-
-    def xend_domain_vbd(self, id, vbd):
-        return xend_get(self.domainurl(id),
-                        {'op'       : 'vbd',
-                         'vbd'      : vbd})
-
-    def xend_consoles(self):
-        return xend_get(self.consoleurl())
-
-    def xend_console(self, id):
-        return xend_get(self.consoleurl(id))
-
-    def xend_vnets(self):
-        return xend_get(self.vneturl())
-
-    def xend_vnet_create(self, conf):
-        return xend_call(self.vneturl(),
-                         {'op': 'create', 'config': fileof(conf) })
-
-    def xend_vnet(self, id):
-        return xend_get(self.vneturl(id))
-
-    def xend_vnet_delete(self, id):
-        return xend_call(self.vneturl(id),
-                         {'op': 'delete'})
-
-    def xend_event_inject(self, sxpr):
-        val = xend_call(self.eventurl(),
-                        {'op': 'inject', 'event': fileof(sxpr) })
-    
-
-def main(argv):
-    """Call an API function:
-    
-    python XendClient.py fn args...
-
-    The leading 'xend_' on the function can be omitted.
-    Example:
-
-    > python XendClient.py domains
-    (domain 0 8)
-    > python XendClient.py domain 0
-    (domain (id 0) (name Domain-0) (memory 128))
-    """
-    server = Xend()
-    fn = argv[1]
-    if not fn.startswith('xend'):
-        fn = 'xend_' + fn
-    args = argv[2:]
-    val = getattr(server, fn)(*args)
-    PrettyPrint.prettyprint(val)
-    print
-
-if __name__ == "__main__":
-    main(sys.argv)
-else:    
-    server = Xend()
diff --git a/tools/xen/lib/xend/XendConsole.py b/tools/xen/lib/xend/XendConsole.py
deleted file mode 100644 (file)
index 4420c38..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-import socket
-import xen.ext.xc
-xc = xen.ext.xc.new()
-
-import sxp
-import XendRoot
-xroot = XendRoot.instance()
-import XendDB
-
-import EventServer
-eserver = EventServer.instance()
-
-from xen.xend.server import SrvDaemon
-daemon = SrvDaemon.instance()
-
-class XendConsoleInfo:
-    """Console information record.
-    """
-
-    def __init__(self, console, dom1, port1, dom2, port2, conn=None):
-        self.console = console
-        self.dom1  = int(dom1)
-        self.port1 = int(port1)
-        self.dom2  = int(dom2)
-        self.port2 = int(port2)
-        self.conn  = conn
-        #self.id = "%d.%d-%d.%d" % (self.dom1, self.port1, self.dom2, self.port2)
-        self.id = str(port1)
-
-    def __str__(self):
-        s = "console"
-        s += " id=%s" % self.id
-        s += " src=%d.%d" % (self.dom1, self.port1)
-        s += " dst=%d.%d" % (self.dom2, self.port2)
-        s += " port=%s" % self.console
-        if self.conn:
-            s += " conn=%s:%s" % (self.conn[0], self.conn[1])
-        return s
-
-    def sxpr(self):
-        sxpr = ['console',
-                ['id', self.id],
-                ['src', self.dom1, self.port1],
-                ['dst', self.dom2, self.port2],
-                ['port', self.console],
-                ]
-        if self.conn:
-            sxpr.append(['connected', self.conn[0], self.conn[1]])
-        return sxpr
-
-    def connection(self):
-        return self.conn
-
-    def update(self, consinfo):
-        conn = sxp.child(consinfo, 'connected')
-        if conn:
-            self.conn = conn[1:]
-        else:
-            self.conn = None
-
-    def uri(self):
-        """Get the uri to use to connect to the console.
-        This will be a telnet: uri.
-
-        return uri
-        """
-        host = socket.gethostname()
-        return "telnet://%s:%s" % (host, self.console)
-
-class XendConsole:
-
-    dbpath = "console"
-
-    def  __init__(self):
-        self.db = XendDB.XendDB(self.dbpath)
-        self.console = {}
-        self.console_db = self.db.fetchall("")
-        if xroot.get_rebooted():
-            print 'XendConsole> rebooted: removing all console info'
-            self.rm_all()
-        eserver.subscribe('xend.domain.died', self.onDomainDied)
-        eserver.subscribe('xend.domain.destroy', self.onDomainDied)
-
-    def rm_all(self):
-        """Remove all console info. Used after reboot.
-        """
-        for (k, v) in self.console_db.items():
-            self._delete_console(k)
-
-    def refresh(self):
-        consoles = daemon.consoles()
-        cons = {}
-        for consinfo in consoles:
-            id = str(sxp.child_value(consinfo, 'id'))
-            cons[id] = consinfo
-            if id not in self.console:
-                self._new_console(consinfo)
-        for c in self.console.values():
-            consinfo = cons.get(c.id)
-            if consinfo:
-                c.update(consinfo)
-            else:
-                self._delete_console(c.id)
-
-    def onDomainDied(self, event, val):
-        dom = int(val)
-        #print 'XendConsole>onDomainDied', 'event', event, "dom=", dom
-        for c in self.consoles():
-            #print 'onDomainDied', "dom=", dom, "dom1=", c.dom1, "dom2=", c.dom2
-            if (c.dom1 == dom) or (c.dom2 == dom):
-                'XendConsole>onDomainDied', 'delete console dom=', dom
-                ctrl = daemon.get_domain_console(dom)
-                if ctrl:
-                    ctrl.close()
-                self._delete_console(c.id)
-
-    def sync(self):
-        self.db.saveall("", self.console_db)
-
-    def sync_console(self, id):
-        self.db.save(id, self.console_db[id])
-
-    def _new_console(self, consinfo):
-        # todo: xen needs a call to get current domain id.
-        dom1 = 0
-        port1 = sxp.child_value(consinfo, 'local_port')
-        dom2 = sxp.child_value(consinfo, 'domain')
-        port2 = sxp.child_value(consinfo, 'remote_port')
-        console = sxp.child_value(consinfo, 'console_port')
-        info = XendConsoleInfo(console, dom1, int(port1), int(dom2), int(port2))
-        info.update(consinfo)
-        self._add_console(info.id, info)
-        return info
-
-    def _add_console(self, id, info):
-        self.console[id] = info
-        self.console_db[id] = info.sxpr()
-        self.sync_console(id)
-
-    def _delete_console(self, id):
-        if id in self.console:
-            del self.console[id]
-        if id in self.console_db:
-            del self.console_db[id]
-            self.db.delete(id)
-
-    def console_ls(self):
-        self.refresh()
-        return self.console.keys()
-
-    def consoles(self):
-        self.refresh()
-        return self.console.values()
-    
-    def console_create(self, dom):
-        consinfo = daemon.console_create(dom)
-        info = self._new_console(consinfo)
-        return info
-    
-    def console_get(self, id):
-        self.refresh()
-        return self.console.get(id)
-
-    def console_delete(self, id):
-        self._delete_console(id)
-
-    def console_disconnect(self, id):
-        id = int(id)
-        daemon.console_disconnect(id)
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendConsole()
-    return inst
diff --git a/tools/xen/lib/xend/XendDB.py b/tools/xen/lib/xend/XendDB.py
deleted file mode 100644 (file)
index 6a27e65..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-import os
-import os.path
-import errno
-import dircache
-import time
-
-import sxp
-import XendRoot
-xroot = XendRoot.instance()
-
-class XendDB:
-    """Persistence for Xend. Stores data in files and directories.
-    """
-
-    def __init__(self, path=None):
-        self.dbpath = xroot.get_dbroot()
-        if path:
-            self.dbpath = os.path.join(self.dbpath, path)
-        pass
-
-    def filepath(self, path):
-        return os.path.join(self.dbpath, path)
-        
-    def fetch(self, path):
-        fpath = self.filepath(path)
-        return self.fetchfile(fpath)
-
-    def fetchfile(self, fpath):
-        pin = sxp.Parser()
-        fin = file(fpath, "rb")
-        try:
-            while 1:
-                try:
-                    buf = fin.read(1024)
-                except IOError, ex:
-                    if ex.errno == errno.EINTR:
-                        continue
-                    else:
-                        raise
-                pin.input(buf)
-                if buf == '':
-                    pin.input_eof()
-                    break
-        finally:
-            fin.close()
-        return pin.get_val()
-
-    def save(self, path, sxpr):
-        fpath = self.filepath(path)
-        return self.savefile(fpath, sxpr)
-    
-    def savefile(self, fpath, sxpr):
-        fdir = os.path.dirname(fpath)
-        if not os.path.isdir(fdir):
-            os.makedirs(fdir)
-        fout = file(fpath, "wb+")
-        try:
-            t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
-            fout.write("# %s %s\n" % (fpath, t))
-            sxp.show(sxpr, out=fout)
-        finally:
-            fout.close()
-
-    def fetchall(self, path):
-        dpath = self.filepath(path)
-        d = {}
-        for k in dircache.listdir(dpath):
-            try:
-                v = self.fetchfile(os.path.join(dpath, k))
-                d[k] = v
-            except:
-                pass
-        return d
-
-    def saveall(self, path, d):
-        for (k, v) in d.items():
-            self.save(os.path.join(path, k), v)
-
-    def delete(self, path):
-        dpath = self.filepath(path)
-        os.unlink(dpath)
-
-    def ls(self, path):
-        dpath = self.filepath(path)
-        return dircache.listdir(dpath)
-            
-        
-
-        
diff --git a/tools/xen/lib/xend/XendDomain.py b/tools/xen/lib/xend/XendDomain.py
deleted file mode 100644 (file)
index 3aaf080..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Handler for domain operations.
- Nothing here is persistent (across reboots).
- Needs to be persistent for one uptime.
-"""
-import sys
-
-from twisted.internet import defer
-
-import xen.ext.xc; xc = xen.ext.xc.new()
-
-import sxp
-import XendRoot
-xroot = XendRoot.instance()
-import XendDB
-import XendDomainInfo
-import XendConsole
-import EventServer
-
-from xen.xend.server import SrvDaemon
-xend = SrvDaemon.instance()
-
-eserver = EventServer.instance()
-
-__all__ = [ "XendDomain" ]
-        
-class XendDomain:
-    """Index of all domains. Singleton.
-    """
-    
-    dbpath = "domain"
-    domain = {}
-    
-    def __init__(self):
-        self.xconsole = XendConsole.instance()
-        # Table of domain info indexed by domain id.
-        self.db = XendDB.XendDB(self.dbpath)
-        #self.domain = {}
-        self.domain_db = self.db.fetchall("")
-        if xroot.get_rebooted():
-            print 'XendDomain> rebooted: removing all domain info'
-            self.rm_all()
-        eserver.subscribe('xend.virq', self.onVirq)
-        self.initial_refresh()
-
-    def onVirq(self, event, val):
-        print 'XendDomain> virq', val
-        self.reap()
-
-    def rm_all(self):
-        """Remove all domain info. Used after reboot.
-        """
-        for (k, v) in self.domain_db.items():
-            self._delete_domain(k, notify=0)
-            
-    def initial_refresh(self):
-        """Refresh initial domain info from domain_db.
-        """
-        print "initial_refresh>"
-        for d in self.domain_db.values(): print 'db dom=', d
-        domlist = xc.domain_getinfo()
-        for d in domlist: print 'xc dom=', d
-        doms = {}
-        for d in domlist:
-            domid = str(d['dom'])
-            doms[domid] = d
-        dlist = []
-        for config in self.domain_db.values():
-            domid = str(sxp.child_value(config, 'id'))
-            print "dom=", domid, "config=", config
-            if domid in doms:
-                print "dom=", domid, "new"
-                deferred = self._new_domain(config, doms[domid])
-                dlist.append(deferred)
-            else:
-                print "dom=", domid, "del"
-                self._delete_domain(domid)
-        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
-        def cbok(val):
-            #print "doms:"
-            #for d in self.domain.values(): print 'dom', d
-            self.refresh()
-            print "XendDomain>initial_refresh> doms:"
-            for d in self.domain.values(): print 'dom', d
-        deferred.addCallback(cbok)
-
-    def sync(self):
-        """Sync domain db to disk.
-        """
-        self.db.saveall("", self.domain_db)
-
-    def sync_domain(self, dom):
-        """Sync info for a domain to disk.
-
-        dom    domain id (string)
-        """
-        self.db.save(dom, self.domain_db[dom])
-
-    def close(self):
-        pass
-
-    def _new_domain(self, savedinfo, info):
-        """Create a domain entry from saved info.
-        """
-##         console = None
-##         kernel = None
-##         id = sxp.child_value(info, 'id')
-##         dom = int(id)
-##         name = sxp.child_value(info, 'name')
-##         memory = int(sxp.child_value(info, 'memory'))
-##         consoleinfo = sxp.child(info, 'console')
-##         if consoleinfo:
-##             consoleid = sxp.child_value(consoleinfo, 'id')
-##             console = self.xconsole.console_get(consoleid)
-##         if dom and console is None:
-##             # Try to connect a console.
-##             console = self.xconsole.console_create(dom)
-##         config = sxp.child(info, 'config')
-##         if config:
-##             image = sxp.child(info, 'image')
-##             if image:
-##                 image = sxp.child0(image)
-##                 kernel = sxp.child_value(image, 'kernel')
-##         dominfo = XendDomainInfo.XendDomainInfo(
-##             config, dom, name, memory, kernel, console)
-        config = sxp.child_value(savedinfo, 'config')
-        deferred = XendDomainInfo.vm_recreate(config, info)
-        def fn(dominfo):
-            self.domain[dominfo.id] = dominfo
-        deferred.addCallback(fn)
-        return deferred
-
-    def _add_domain(self, id, info, notify=1):
-        self.domain[id] = info
-        self.domain_db[id] = info.sxpr()
-        self.sync_domain(id)
-        if notify: eserver.inject('xend.domain.created', id)
-
-    def _delete_domain(self, id, notify=1):
-        if id in self.domain:
-            if notify: eserver.inject('xend.domain.died', id)
-            del self.domain[id]
-        if id in self.domain_db:
-            del self.domain_db[id]
-            self.db.delete(id)
-
-    def reap(self):
-        """Go through the domains looking for ones that have crashed or stopped.
-        Tidy them up.
-        """
-        print 'XendDomain>reap>'
-        domlist = xc.domain_getinfo()
-        casualties = []
-        for d in domlist:
-            #print 'dom', d
-            dead = 0
-            dead = dead or (d['crashed'] or d['shutdown'])
-            dead = dead or (d['dying'] and
-                            not(d['running'] or d['paused'] or d['blocked']))
-            if dead:
-                casualties.append(d)
-        for d in casualties:
-            id = str(d['dom'])
-            print 'XendDomain>reap> died id=', id, d
-            dominfo = self.domain.get(id)
-            if not dominfo: continue
-            dominfo.died()
-            self.domain_destroy(id, refresh=0)
-        print 'XendDomain>reap<'
-
-    def refresh(self):
-        """Refresh domain list from Xen.
-        """
-        domlist = xc.domain_getinfo()
-        # Index the domlist by id.
-        # Add entries for any domains we don't know about.
-        doms = {}
-        for d in domlist:
-            id = str(d['dom'])
-            doms[id] = d
-            if id not in self.domain:
-                config = None
-                #image = None
-                #newinfo = XendDomainInfo.XendDomainInfo(
-                #    config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d)
-                deferred = XendDomainInfo.vm_recreate(config, d)
-                def fn(dominfo):
-                    self._add_domain(dominfo.id, dominfo)
-                deferred.addCallback(fn)
-        # Remove entries for domains that no longer exist.
-        for d in self.domain.values():
-            dominfo = doms.get(d.id)
-            if dominfo:
-                d.update(dominfo)
-            else:
-                self._delete_domain(d.id)
-        self.reap()
-
-    def refresh_domain(self, id):
-        dom = int(id)
-        dominfo = xc.domain_getinfo(dom, 1)
-        if dominfo == [] or dominfo[0]['dom'] != dom:
-            try:
-                self._delete_domain(id)
-            except:
-                print 'refresh_domain: error'
-                raise
-                pass
-        else:
-            d = self.domain.get(id)
-            if d:
-                d.update(dominfo[0])
-
-    def domain_ls(self):
-        # List domains.
-        # Update info from kernel first.
-        self.refresh()
-        return self.domain.keys()
-
-    def domains(self):
-        self.refresh()
-        return self.domain.values()
-    
-    def domain_create(self, config):
-        # Create domain, log it.
-        deferred = XendDomainInfo.vm_create(config)
-        def fn(dominfo):
-            self._add_domain(dominfo.id, dominfo)
-            return dominfo
-        deferred.addCallback(fn)
-        return deferred
-    
-    def domain_get(self, id):
-        id = str(id)
-        self.refresh_domain(id)
-        return self.domain.get(id)
-    
-    def domain_unpause(self, id):
-        """(Re)start domain running.
-        """
-        dom = int(id)
-        eserver.inject('xend.domain.unpause', id)
-        return xc.domain_unpause(dom=dom)
-    
-    def domain_pause(self, id):
-        """Pause domain execution.
-        """
-        dom = int(id)
-        eserver.inject('xend.domain.pause', id)
-        return xc.domain_pause(dom=dom)
-    
-    def domain_shutdown(self, id, reason='poweroff'):
-        """Shutdown domain (nicely).
-        """
-        dom = int(id)
-        if dom <= 0:
-            return 0
-        eserver.inject('xend.domain.shutdown', [id, reason])
-        val = xend.domain_shutdown(dom, reason)
-        self.refresh()
-        return val
-    
-    def domain_destroy(self, id, refresh=1):
-        """Terminate domain immediately.
-        """
-        dom = int(id)
-        if dom <= 0:
-            return 0
-        eserver.inject('xend.domain.destroy', id)
-        val = xc.domain_destroy(dom=dom)
-        if refresh: self.refresh()
-        return val       
-
-    def domain_migrate(self, id, dst):
-        """Start domain migration.
-        """
-        # Need a cancel too?
-        pass
-
-    def domain_save(self, id, dst, progress=0):
-        """Save domain state to file, destroy domain.
-        """
-        dom = int(id)
-        dominfo = self.domain_get(id)
-        if not dominfo:
-            return -1
-        vmconfig = sxp.to_string(dominfo.sxpr())
-        self.domain_pause(id)
-        eserver.inject('xend.domain.save', id)
-        rc = xc.linux_save(dom=dom, state_file=dst, vmconfig=vmconfig, progress=progress)
-        if rc == 0:
-            self.domain_destroy(id)
-        return rc
-    
-    def domain_restore(self, src, progress=0):
-        """Restore domain from file.
-        """
-        dominfo = XendDomainInfo.vm_restore(src, progress=progress)
-        self._add_domain(dominfo.id, dominfo)
-        return dominfo
-    
-    #============================================================================
-    # Backward compatibility stuff from here on.
-
-    def domain_pincpu(self, dom, cpu):
-        dom = int(dom)
-        return xc.domain_pincpu(dom, cpu)
-
-    def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu):
-        dom = int(dom)
-        return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv,
-                                      warp=warp, warpl=warpl, warpu=warpu)
-
-    def domain_cpu_bvt_get(self, dom):
-        dom = int(dom)
-        return xc.bvtsched_domain_get(dom)
-    
-    def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime):
-        dom = int(dom)
-        return xc.atropos_domain_set(dom, period, slice, latency, xtratime)
-
-    def domain_cpu_atropos_get(self, dom):
-        dom = int(dom)
-        return xc.atropos_domain_get(dom)
-
-    def domain_vif_ls(self, dom):
-        dominfo = self.domain_get(dom)
-        if not dominfo: return None
-        devs = dominfo.get_devices('vif')
-        return range(0, len(devs))
-
-    def domain_vif_get(self, dom, vif):
-        dominfo = self.domain_get(dom)
-        if not dominfo: return None
-        return dominfo.get_device_by_index(vif)
-
-##     def domain_vif_ip_add(self, dom, vif, ip):
-##         dom = int(dom)
-##         return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip)
-
-    def domain_vbd_ls(self, dom):
-        dominfo = self.domain_get(dom)
-        if not dominfo: return []
-        devs = dominfo.get_devices('vbd')
-        return [ sxp.child_value(v, 'dev') for v in devs ]
-
-    def domain_vbd_get(self, dom, vbd):
-        dominfo = self.domain_get(dom)
-        if not dominfo: return None
-        devs = dominfo.get_devices('vbd')
-        for v in devs:
-            if sxp.child_value(v, 'dev') == vbd:
-                return v
-        return None
-
-    def domain_shadow_control(self, dom, op):
-        dom = int(dom)
-        return xc.shadow_control(dom, op)
-
-    #============================================================================
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendDomain()
-    return inst
diff --git a/tools/xen/lib/xend/XendDomainConfig.py b/tools/xen/lib/xend/XendDomainConfig.py
deleted file mode 100644 (file)
index 35db31f..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Handler for persistent domain configs.
-
-"""
-
-import sxp
-import XendDB
-import XendDomain
-
-__all__ = [ "XendDomainConfig" ]
-
-class XendDomainConfig:
-
-    dbpath = 'config'
-
-    def __init__(self):
-        self.db = XendDB.XendDB(self.dbpath)
-
-    def domain_config_ls(self, path):
-        return self.db.ls(path)
-
-    def domain_config_create(self, path, sxpr):
-        self.db.save(path, sxpr)
-        pass
-
-    def domain_config_delete(self, path):
-        self.db.delete(path)
-
-    def domain_config_instance(self, path):
-        """Create a domain from a config.
-        """
-        config = self.db.fetch(path)
-        xd = XendDomain.instance()
-        newdom = xd.domain_create(config)
-        return newdom
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendDomainConfig()
-    return inst
diff --git a/tools/xen/lib/xend/XendDomainInfo.py b/tools/xen/lib/xend/XendDomainInfo.py
deleted file mode 100644 (file)
index a7e5aa3..0000000
+++ /dev/null
@@ -1,908 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Representation of a single domain.
-Includes support for domain construction, using
-open-ended configurations.
-
-Author: Mike Wray <mike.wray@hpl.hp.com>
-
-"""
-
-import string
-import re
-import sys
-import os
-
-from twisted.internet import defer
-
-import xen.ext.xc; xc = xen.ext.xc.new()
-import xen.util.ip
-
-import sxp
-
-import XendConsole
-xendConsole = XendConsole.instance()
-
-import server.SrvDaemon
-xend = server.SrvDaemon.instance()
-
-SIF_BLK_BE_DOMAIN = (1<<4)
-SIF_NET_BE_DOMAIN = (1<<5)
-
-def readlines(fd):
-    """Version of readlines safe against EINTR.
-    """
-    import errno
-    
-    lines = []
-    while 1:
-        try:
-            line = fd.readline()
-        except IOError, ex:
-            if ex.errno == errno.EINTR:
-                continue
-            else:
-                raise
-        if line == '': break
-        lines.append(line)
-    return lines
-
-class VmError(ValueError):
-    """Vm construction error."""
-
-    def __init__(self, value):
-        self.value = value
-
-    def __str__(self):
-        return self.value
-
-
-def blkdev_name_to_number(name):
-    """Take the given textual block-device name (e.g., '/dev/sda1',
-    'hda') and return the device number used by the OS. """
-
-    if not re.match( '/dev/', name ):
-        name = '/dev/' + name
-        
-    return os.stat(name).st_rdev
-
-def lookup_raw_partn(partition):
-    """Take the given block-device name (e.g., '/dev/sda1', 'hda')
-    and return a dictionary { device, start_sector,
-    nr_sectors, type }
-        device:       Device number of the given partition
-        start_sector: Index of first sector of the partition
-        nr_sectors:   Number of sectors comprising this partition
-        type:         'Disk' or identifying name for partition type
-    """
-
-    if not re.match( '/dev/', partition ):
-        partition = '/dev/' + partition
-
-    drive = re.split( '[0-9]', partition )[0]
-
-    if drive == partition:
-        fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
-        line = readline(fd)
-        if line:
-            return [ { 'device' : blkdev_name_to_number(drive),
-                       'start_sector' : long(0),
-                       'nr_sectors' : long(line) * 2,
-                       'type' : 'Disk' } ]
-        return None
-
-    # determine position on disk
-    fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' )
-
-    #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012']
-    lines = readlines(fd)
-    for line in lines:
-        m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
-                       'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
-        if m:
-            return [ { 'device' : blkdev_name_to_number(drive),
-                       'start_sector' : long(m.group(1)),
-                       'nr_sectors' : long(m.group(2)),
-                       'type' : m.group(3) } ]
-    
-    return None
-
-def lookup_disk_uname(uname):
-    """Lookup a list of segments for a physical device.
-    uname [string]:  name of the device in the format \'phy:dev\' for a physical device
-    returns [list of dicts]: list of extents that make up the named device
-    """
-    ( type, d_name ) = string.split( uname, ':' )
-
-    if type == "phy":
-        segments = lookup_raw_partn( d_name )
-    else:
-        segments = None
-    return segments
-
-def make_disk(dom, uname, dev, mode, recreate=0):
-    """Create a virtual disk device for a domain.
-
-    @returns Deferred
-    """
-    segments = lookup_disk_uname(uname)
-    if not segments:
-        raise VmError("vbd: Segments not found: uname=%s" % uname)
-    if len(segments) > 1:
-        raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname)
-    segment = segments[0]
-    vdev = blkdev_name_to_number(dev)
-    ctrl = xend.blkif_create(dom, recreate=recreate)
-    
-    def fn(ctrl):
-        return xend.blkif_dev_create(dom, vdev, mode, segment, recreate=recreate)
-    ctrl.addCallback(fn)
-    return ctrl
-        
-def make_vif(dom, vif, vmac, recreate=0):
-    """Create a virtual network device for a domain.
-
-    
-    @returns Deferred
-    """
-    xend.netif_create(dom, recreate=recreate)
-    d = xend.netif_dev_create(dom, vif, vmac, recreate=recreate)
-    return d
-
-def vif_up(iplist):
-    """send an unsolicited ARP reply for all non link-local IP addresses.
-
-    iplist IP addresses
-    """
-
-    IP_NONLOCAL_BIND = '/proc/sys/net/ipv4/ip_nonlocal_bind'
-    
-    def get_ip_nonlocal_bind():
-        return int(open(IP_NONLOCAL_BIND, 'r').read()[0])
-
-    def set_ip_nonlocal_bind(v):
-        print >> open(IP_NONLOCAL_BIND, 'w'), str(v)
-
-    def link_local(ip):
-        return xen.util.ip.check_subnet(ip, '169.254.0.0', '255.255.0.0')
-
-    def arping(ip, gw):
-        cmd = '/usr/sbin/arping -A -b -I eth0 -c 1 -s %s %s' % (ip, gw)
-        print cmd
-        os.system(cmd)
-        
-    gateway = xen.util.ip.get_current_ipgw() or '255.255.255.255'
-    nlb = get_ip_nonlocal_bind()
-    if not nlb: set_ip_nonlocal_bind(1)
-    try:
-        for ip in iplist:
-            if not link_local(ip):
-                arping(ip, gateway)
-    finally:
-        if not nlb: set_ip_nonlocal_bind(0)
-
-config_handlers = {}
-
-def add_config_handler(name, h):
-    """Add a handler for a config field.
-
-    name     field name
-    h        handler: fn(vm, config, field, index)
-    """
-    config_handlers[name] = h
-
-def get_config_handler(name):
-    """Get a handler for a config field.
-
-    returns handler or None
-    """
-    return config_handlers.get(name)
-
-"""Table of handlers for virtual machine images.
-Indexed by image type.
-"""
-image_handlers = {}
-
-def add_image_handler(name, h):
-    """Add a handler for an image type
-    name     image type
-    h        handler: fn(config, name, memory, image)
-    """
-    image_handlers[name] = h
-
-def get_image_handler(name):
-    """Get the handler for an image type.
-    name     image type
-
-    returns handler or None
-    """
-    return image_handlers.get(name)
-
-"""Table of handlers for devices.
-Indexed by device type.
-"""
-device_handlers = {}
-
-def add_device_handler(name, h):
-    """Add a handler for a device type.
-
-    name      device type
-    h         handler: fn(vm, dev)
-    """
-    device_handlers[name] = h
-
-def get_device_handler(name):
-    """Get the handler for a device type.
-
-    name      device type
-
-    returns handler or None
-    """
-    return device_handlers.get(name)
-
-def vm_create(config):
-    """Create a VM from a configuration.
-    If a vm has been partially created and there is an error it
-    is destroyed.
-
-    config    configuration
-
-    returns Deferred
-    raises VmError for invalid configuration
-    """
-    print 'vm_create>'
-    vm = XendDomainInfo()
-    return vm.construct(config)
-
-def vm_recreate(config, info):
-    """Create the VM object for an existing domain.
-    """
-    vm = XendDomainInfo()
-    vm.recreate = 1
-    vm.setdom(info['dom'])
-    vm.name = info['name']
-    vm.memory = info['mem_kb']/1024
-    if config:
-        d = vm.construct(config)
-    else:
-        d = defer.Deferred()
-        d.callback(vm)
-    return d
-
-def vm_restore(src, progress=0):
-    """Restore a VM from a disk image.
-
-    src      saved state to restore
-    progress progress reporting flag
-    returns  deferred
-    raises   VmError for invalid configuration
-    """
-    vm = XendDomainInfo()
-    ostype = "linux" #todo Set from somewhere (store in the src?).
-    restorefn = getattr(xc, "%s_restore" % ostype)
-    d = restorefn(state_file=src, progress=progress)
-    dom = int(d['dom'])
-    if dom < 0:
-        raise VMError('restore failed')
-    vmconfig = sxp.from_string(d['vmconfig'])
-    vm.config = sxp.child_value(vmconfig, 'config')
-    deferred = vm.dom_configure(dom)
-    def vifs_cb(val, vm):
-        vif_up(vm.ipaddrs)
-    deferred.addCallback(vifs_cb, vm)
-    return deferred
-    
-def dom_get(dom):
-    domlist = xc.domain_getinfo(dom=dom)
-    if domlist and dom == domlist[0]['dom']:
-        return domlist[0]
-    return None
-    
-
-def append_deferred(dlist, v):
-    if isinstance(v, defer.Deferred):
-        dlist.append(v)
-
-def _vm_configure1(val, vm):
-    d = vm.create_devices()
-    print '_vm_configure1> made devices...'
-    def cbok(x):
-        print '_vm_configure1> cbok', x
-        return x
-    d.addCallback(cbok)
-    d.addCallback(_vm_configure2, vm)
-    print '_vm_configure1<'
-    return d
-
-def _vm_configure2(val, vm):
-    print '>callback _vm_configure2...'
-    d = vm.configure_fields()
-    def cbok(results):
-        print '_vm_configure2> cbok', results
-        return vm
-    def cberr(err):
-        print '_vm_configure2> cberr', err
-        vm.destroy()
-        return err
-    d.addCallback(cbok)
-    d.addErrback(cberr)
-    print '<_vm_configure2'
-    return d
-
-class XendDomainInfo:
-    """Virtual machine object."""
-
-    def __init__(self):
-        self.recreate = 0
-        self.config = None
-        self.id = None
-        self.dom = None
-        self.name = None
-        self.memory = None
-        self.image = None
-        self.ramdisk = None
-        self.cmdline = None
-        self.console = None
-        self.devices = {}
-        self.configs = []
-        self.info = None
-        self.ipaddrs = []
-        self.blkif_backend = 0
-        self.netif_backend = 0
-        #todo: state: running, suspended
-        self.state = 'running'
-        #todo: set to migrate info if migrating
-        self.migrate = None
-
-    def setdom(self, dom):
-        self.dom = int(dom)
-        self.id = str(dom)
-        
-    def update(self, info):
-        """Update with  info from xc.domain_getinfo().
-        """
-        self.info = info
-        self.memory = self.info['mem_kb'] / 1024
-
-    def __str__(self):
-        s = "domain"
-        s += " id=" + self.id
-        s += " name=" + self.name
-        s += " memory=" + str(self.memory)
-        if self.console:
-            s += " console=" + self.console.id
-        if self.image:
-            s += " image=" + self.image
-        s += ""
-        return s
-
-    __repr__ = __str__
-
-    def sxpr(self):
-        sxpr = ['domain',
-                ['id', self.id],
-                ['name', self.name],
-                ['memory', self.memory] ]
-        if self.info:
-            run   = (self.info['running'] and 'r') or '-'
-            block = (self.info['blocked'] and 'b') or '-'
-            stop  = (self.info['paused']  and 'p') or '-'
-            susp  = (self.info['shutdown'] and 's') or '-'
-            crash = (self.info['crashed'] and 'c') or '-'
-            state = run + block + stop + susp + crash
-            sxpr.append(['state', state])
-            if self.info['shutdown']:
-                reasons = ["poweroff", "reboot", "suspend"]
-                reason = reasons[self.info['shutdown_reason']]
-                sxpr.append(['shutdown_reason', reason])
-            sxpr.append(['cpu', self.info['cpu']])
-            sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
-        if self.console:
-            sxpr.append(self.console.sxpr())
-        if self.config:
-            sxpr.append(['config', self.config])
-        return sxpr
-
-    def construct(self, config):
-        # todo - add support for scheduling params?
-        self.config = config
-        try:
-            self.name = sxp.child_value(config, 'name')
-            self.memory = int(sxp.child_value(config, 'memory', '128'))
-            self.configure_backends()
-            image = sxp.child_value(config, 'image')
-            image_name = sxp.name(image)
-            image_handler = get_image_handler(image_name)
-            if image_handler is None:
-                raise VmError('unknown image type: ' + image_name)
-            image_handler(self, image)
-            deferred = self.configure()
-        except StandardError, ex:
-            # Catch errors, cleanup and re-raise.
-            self.destroy()
-            raise
-        def cbok(x):
-            print 'vm_create> cbok', x
-            return x
-        deferred.addCallback(cbok)
-        print 'vm_create<'
-        return deferred
-
-    def config_devices(self, name):
-        """Get a list of the 'device' nodes of a given type from the config.
-
-        name   device type
-        return list of device configs
-        """
-        devices = []
-        for d in sxp.children(self.config, 'device'):
-            dev = sxp.child0(d)
-            if dev is None: continue
-            if name == sxp.name(dev):
-                devices.append(dev)
-        return devices
-
-    def add_device(self, type, dev):
-        """Add a device to a virtual machine.
-
-        dev      device to add
-        """
-        dl = self.devices.get(type, [])
-        dl.append(dev)
-        self.devices[type] = dl
-
-    def get_devices(self, type):
-        val = self.devices.get(type, [])
-        return val
-
-    def get_device_by_id(self, type, id):
-        """Get the device with the given id.
-
-        id       device id
-
-        returns  device or None
-        """
-        dl = self.get_devices(type)
-        for d in dl:
-            if d.getprop('id') == id:
-                return d
-        return None
-
-    def get_device_by_index(self, type, idx):
-        """Get the device with the given index.
-
-        idx       device index
-
-        returns  device or None
-        """
-        dl = self.get_devices(type)
-        if 0 <= idx < len(dl):
-            return dl[idx]
-        else:
-            return None
-
-    def add_config(self, val):
-        """Add configuration data to a virtual machine.
-
-        val      data to add
-        """
-        self.configs.append(val)
-
-    def destroy(self):
-        if self.dom <= 0:
-            return 0
-        return xc.domain_destroy(dom=self.dom)
-
-    def died(self):
-        print 'died>', self.dom
-        self.release_devices()
-
-    def release_devices(self):
-        print 'release_devices>', self.dom
-        self.release_vifs()
-        self.release_vbds()
-        self.devices = {}
-
-    def release_vifs(self):
-        print 'release_vifs>', self.dom
-        if self.dom is None: return
-        ctrl = xend.netif_get(self.dom)
-        if ctrl:
-            ctrl.destroy()
-
-    def release_vbds(self):
-        print 'release_vbds>', self.dom
-        if self.dom is None: return
-        ctrl = xend.blkif_get(self.dom)
-        if ctrl:
-            ctrl.destroy()
-
-    def show(self):
-        """Print virtual machine info.
-        """
-        print "[VM dom=%d name=%s memory=%d" % (self.dom, self.name, self.memory)
-        print "image:"
-        sxp.show(self.image)
-        print
-        for dl in self.devices:
-            for dev in dl:
-                print "device:"
-                sxp.show(dev)
-                print
-        for val in self.configs:
-            print "config:"
-            sxp.show(val)
-            print
-        print "]"
-
-    def init_domain(self):
-        """Initialize the domain memory.
-        """
-        if self.recreate: return
-        memory = self.memory
-        name = self.name
-        cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
-        print 'init_domain>', memory, name, cpu
-        dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
-        if dom <= 0:
-            raise VmError('Creating domain failed: name=%s memory=%d'
-                          % (name, memory))
-        self.setdom(dom)
-
-    def build_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
-        """Build the domain boot image.
-        """
-        if self.recreate: return
-        if len(cmdline) >= 256:
-            print 'Warning: kernel cmdline too long'
-        dom = self.dom
-        buildfn = getattr(xc, '%s_build' % ostype)
-        print 'build_domain>', ostype, dom, kernel, cmdline, ramdisk
-        flags = 0
-        if self.netif_backend: flags |= SIF_NET_BE_DOMAIN
-        if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN
-        err = buildfn(dom            = dom,
-                      image          = kernel,
-                      control_evtchn = self.console.port2,
-                      cmdline        = cmdline,
-                      ramdisk        = ramdisk,
-                      flags          = flags)
-        if err != 0:
-            raise VmError('Building domain failed: type=%s dom=%d err=%d'
-                          % (ostype, dom, err))
-
-    def create_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
-        """Create a domain. Builds the image but does not configure it.
-
-        ostype  OS type
-        kernel  kernel image
-        ramdisk kernel ramdisk
-        cmdline kernel commandline
-        vifs_n  number of network interfaces
-        """
-        print 'create_domain>', ostype, kernel
-        if not self.recreate:
-            if not os.path.isfile(kernel):
-                raise VmError('Kernel image does not exist: %s' % kernel)
-            if ramdisk and not os.path.isfile(ramdisk):
-                raise VMError('Kernel ramdisk does not exist: %s' % ramdisk)
-        print 'create-domain> init_domain...'
-        self.init_domain()
-        print 'create_domain>', 'dom=', self.dom
-        self.console = xendConsole.console_create(self.dom)
-        self.build_domain(ostype, kernel, ramdisk, cmdline, vifs_n)
-        self.image = kernel
-        self.ramdisk = ramdisk
-        self.cmdline = cmdline
-
-    def create_devices(self):
-        """Create the devices for a vm.
-
-        returns Deferred
-        raises VmError for invalid devices
-        """
-        print '>create_devices'
-        dlist = []
-        devices = sxp.children(self.config, 'device')
-        index = {}
-        for d in devices:
-            dev = sxp.child0(d)
-            if dev is None:
-                raise VmError('invalid device')
-            dev_name = sxp.name(dev)
-            dev_index = index.get(dev_name, 0)
-            dev_handler = get_device_handler(dev_name)
-            if dev_handler is None:
-                raise VmError('unknown device type: ' + dev_name)
-            v = dev_handler(self, dev, dev_index)
-            append_deferred(dlist, v)
-            index[dev_name] = dev_index + 1
-        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
-        print '<create_devices'
-        return deferred
-
-    def configure_backends(self):
-        """Set configuration flags if the vm is a backend for netif of blkif.
-        """
-        for c in sxp.children(self.config, 'backend'):
-            name = sxp.name(sxp.child0(c))
-            if name == 'blkif':
-                self.blkif_backend = 1
-            elif name == 'netif':
-                self.netif_backend = 1
-            else:
-                raise VmError('invalid backend type:' + str(name))
-
-    def create_backends(self):
-        """Setup the netif and blkif backends.
-        """
-        if self.blkif_backend:
-            xend.blkif_set_control_domain(self.dom, recreate=self.recreate)
-        if self.netif_backend:
-            xend.netif_set_control_domain(self.dom, recreate=self.recreate)
-            
-    def configure(self):
-        """Configure a vm.
-
-        vm         virtual machine
-        config     configuration
-
-        returns Deferred - calls callback with vm
-        """
-        if self.blkif_backend:
-            d = defer.Deferred()
-            d.callback(1)
-        else:
-            d = xend.blkif_create(self.dom, recreate=self.recreate)
-        d.addCallback(_vm_configure1, self)
-        return d
-
-    def dom_configure(self, dom):
-        """Configure a domain.
-
-        dom    domain id
-        returns deferred
-        """
-        d = dom_get(dom)
-        if not d:
-            raise VMError("Domain not found: %d" % dom)
-        try:
-            self.setdom(dom)
-            self.name = d['name']
-            self.memory = d['memory']/1024
-            deferred = self.configure()
-        except StandardError, ex:
-            self.destroy()
-            raise
-        return deferred
-
-    def configure_fields(self):
-        dlist = []
-        index = {}
-        for field in sxp.children(self.config):
-            field_name = sxp.name(field)
-            field_index = index.get(field_name, 0)
-            field_handler = get_config_handler(field_name)
-            # Ignore unknown fields. Warn?
-            if field_handler:
-                v = field_handler(self, self.config, field, field_index)
-                append_deferred(dlist, v)
-            index[field_name] = field_index + 1
-        d = defer.DeferredList(dlist, fireOnOneErrback=1)
-        return d
-
-
-def vm_image_linux(vm, image):
-    """Create a VM for a linux image.
-
-    name      vm name
-    memory    vm memory
-    image     image config
-
-    returns vm
-    """
-    kernel = sxp.child_value(image, "kernel")
-    cmdline = ""
-    ip = sxp.child_value(image, "ip", "dhcp")
-    if ip:
-        cmdline += " ip=" + ip
-    root = sxp.child_value(image, "root")
-    if root:
-        cmdline += " root=" + root
-    args = sxp.child_value(image, "args")
-    if args:
-        cmdline += " " + args
-    ramdisk = sxp.child_value(image, "ramdisk", '')
-    vifs = vm.config_devices("vif")
-    vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs))
-    return vm
-
-def vm_image_netbsd(vm, image):
-    """Create a VM for a bsd image.
-
-    name      vm name
-    memory    vm memory
-    image     image config
-
-    returns vm
-    """
-    #todo: Same as for linux. Is that right? If so can unify them.
-    kernel = sxp.child_value(image, "kernel")
-    cmdline = ""
-    ip = sxp.child_value(image, "ip", "dhcp")
-    if ip:
-        cmdline += "ip=" + ip
-    root = sxp.child_value(image, "root")
-    if root:
-        cmdline += "root=" + root
-    args = sxp.child_value(image, "args")
-    if args:
-        cmdline += " " + args
-    ramdisk = sxp.child_value(image, "ramdisk")
-    vifs = vm.config_devices("vif")
-    vm.create_domain("netbsd", kernel, ramdisk, cmdline, len(vifs))
-    return vm
-
-
-def vm_dev_vif(vm, val, index):
-    """Create a virtual network interface (vif).
-
-    vm        virtual machine
-    val       vif config
-    index     vif index
-    """
-    if vm.netif_backend:
-        raise VmError('vif: vif in netif backend domain')
-    vif = index #todo
-    vmac = sxp.child_value(val, "mac")
-    defer = make_vif(vm.dom, vif, vmac, vm.recreate)
-    def fn(id):
-        dev = xend.netif_dev(vm.dom, vif)
-        devid = sxp.attribute(val, 'id')
-        if devid:
-            dev.setprop('id', devid)
-        bridge = sxp.child_value(val, "bridge")
-        dev.up(bridge)
-        vm.add_device('vif', dev)
-        print 'vm_dev_vif> created', dev
-        return id
-    defer.addCallback(fn)
-    return defer
-
-def vm_dev_vbd(vm, val, index):
-    """Create a virtual block device (vbd).
-
-    vm        virtual machine
-    val       vbd config
-    index     vbd index
-    """
-    if vm.blkif_backend:
-        raise VmError('vbd: vbd in blkif backend domain')
-    vdev = index
-    uname = sxp.child_value(val, 'uname')
-    if not uname:
-        raise VMError('vbd: Missing uname')
-    dev = sxp.child_value(val, 'dev')
-    if not dev:
-        raise VMError('vbd: Missing dev')
-    mode = sxp.child_value(val, 'mode', 'r')
-    defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
-    def fn(vbd):
-        dev = xend.blkif_dev(vm.dom, vdev)
-        vm.add_device('vbd', dev)
-        return vbd
-    defer.addCallback(fn)
-    return defer
-
-def parse_pci(val):
-    if isinstance(val, StringType):
-        radix = 10
-        if val.startswith('0x') or val.startswith('0X'):
-            radix = 16
-        v = int(val, radix)
-    else:
-        v = val
-    return v
-
-def vm_dev_pci(vm, val, index):
-    bus = sxp.child_value(val, 'bus')
-    if not bus:
-        raise VMError('pci: Missing bus')
-    dev = sxp.child_value(val, 'dev')
-    if not dev:
-        raise VMError('pci: Missing dev')
-    func = sxp.child_value(val, 'func')
-    if not func:
-        raise VMError('pci: Missing func')
-    try:
-        bus = parse_pci(bus)
-        dev = parse_pci(dev)
-        func = parse_pci(func)
-    except:
-        raise VMError('pci: invalid parameter')
-    rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev,
-                                      func=func, enable=1)
-    if rc < 0:
-        #todo non-fatal
-        raise VMError('pci: Failed to configure device: bus=%s dev=%s func=%s' %
-                      (bus, dev, func))
-    return rc
-    
-
-def vm_field_vfr(vm, config, val, index):
-    """Handle a vfr field in a config.
-
-    vm        virtual machine
-    config    vm config
-    val       vfr field
-    """
-    # Get the rules and add them.
-    # (vfr (vif (id foo) (ip x.x.x.x)) ... ) 
-    list = sxp.children(val, 'vif')
-    ipaddrs = []
-    for v in list:
-        id = sxp.child_value(v, 'id')
-        if id is None:
-            raise VmError('vfr: missing vif id')
-        id = int(id)
-        dev = vm.get_device_by_index('vif', id)
-        if not dev:
-            raise VmError('vfr: invalid vif id %d' % id)
-        vif = sxp.child_value(dev, 'vif')
-        ip = sxp.child_value(v, 'ip')
-        if not ip:
-            raise VmError('vfr: missing ip address')
-        ipaddrs.append(ip);
-        # todo: Configure the ipaddrs.
-    vm.ipaddrs = ipaddrs
-
-def vnet_bridge(vnet, vmac, dom, idx):
-    """Add the device for the vif to the bridge for its vnet.
-    """
-    vif = "vif%d.%d" % (dom, idx)
-    try:
-        cmd = "(vif.conn (vif %s) (vnet %s) (vmac %s))" % (vif, vnet, vmac)
-        print "*** vnet_bridge>", cmd
-        out = file("/proc/vnet/policy", "wb")
-        out.write(cmd)
-        err = out.close()
-        print "vnet_bridge>", "err=", err
-    except IOError, ex:
-        print "vnet_bridge>", ex
-    
-def vm_field_vnet(vm, config, val, index):
-    """Handle a vnet field in a config.
-
-    vm        virtual machine
-    config    vm config
-    val       vnet field
-    index     index
-    """
-    # Get the vif children. For each vif look up the vif device
-    # with the given id and configure its vnet.
-    # (vnet (vif (id foo) (vnet 2) (mac x:x:x:x:x:x)) ... )
-    vif_vnets = sxp.children(val, 'vif')
-    for v in vif_vnets:
-        id = sxp.child_value(v, 'id')
-        if id is None:
-            raise VmError('vnet: missing vif id')
-        dev = vm.get_device_by_id('vif', id)
-        #vnet = sxp.child_value(v, 'vnet', 1)
-        #mac = sxp.child_value(dev, 'mac')
-        #vif = sxp.child_value(dev, 'vif')
-        #vnet_bridge(vnet, mac, vm.dom, 0)
-        #vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]])
-
-# Register image handlers for linux and bsd.
-add_image_handler('linux',  vm_image_linux)
-add_image_handler('netbsd', vm_image_netbsd)
-
-# Register device handlers for vifs and vbds.
-add_device_handler('vif',  vm_dev_vif)
-add_device_handler('vbd',  vm_dev_vbd)
-add_device_handler('pci',  vm_dev_pci)
-
-# Register config handlers for vfr and vnet.
-add_config_handler('vfr',  vm_field_vfr)
-add_config_handler('vnet', vm_field_vnet)
diff --git a/tools/xen/lib/xend/XendMigrate.py b/tools/xen/lib/xend/XendMigrate.py
deleted file mode 100644 (file)
index 1580ba8..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-import sys
-import socket
-
-import sxp
-import XendDB
-import EventServer; eserver = EventServer.instance()
-
-class XendMigrateInfo:
-
-    # states: begin, active, failed, succeeded?
-
-    def __init__(self, id, dom, dst):
-        self.id = id
-        self.state = 'begin'
-        self.src_host = socket.gethostname()
-        self.src_dom = dom
-        self.dst_host = dst
-        self.dst_dom = None
-        
-    def set_state(self, state):
-        self.state = state
-
-    def get_state(self):
-        return self.state
-
-    def sxpr(self):
-        sxpr = ['migrate', ['id', self.id], ['state', self.state] ]
-        sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ]
-        sxpr.append(sxpr_src)
-        sxpr_dst = ['dst', ['host', self.dst] ]
-        if self.dst_dom:
-            sxpr_dst.append(['domain', self.dst_dom])
-        sxpr.append(sxpr_dst)
-        return sxpr
-    
-
-class XendMigrate:
-    # Represents migration in progress.
-    # Use log for indications of begin/end/errors?
-    # Need logging of: domain create/halt, migrate begin/end/fail
-    # Log via event server?
-
-    dbpath = "migrate"
-    
-    def __init__(self):
-        self.db = XendDB.XendDB(self.dbpath)
-        self.migrate = {}
-        self.migrate_db = self.db.fetchall("")
-        self.id = 0
-
-    def nextid(self):
-        self.id += 1
-        return "%d" % self.id
-
-    def sync(self):
-        self.db.saveall("", self.migrate_db)
-
-    def sync_migrate(self, id):
-        self.db.save(id, self.migrate_db[id])
-
-    def close(self):
-        pass
-
-    def _add_migrate(self, id, info):
-        self.migrate[id] = info
-        self.migrate_db[id] = info.sxpr()
-        self.sync_migrate(id)
-        #eserver.inject('xend.migrate.begin', info.sxpr())
-
-    def _delete_migrate(self, id):
-        #eserver.inject('xend.migrate.end', id)
-        del self.migrate[id]
-        del self.migrate_db[id]
-        self.db.delete(id)
-
-    def migrate_ls(self):
-        return self.migrate.keys()
-
-    def migrates(self):
-        return self.migrate.values()
-
-    def migrate_get(self, id):
-        return self.migrate.get(id)
-    
-    def migrate_begin(self, dom, dst):
-        # Check dom for existence, not migrating already.
-        # Create migrate info, tell xend to migrate it?
-        # - or fork migrate command ourselves?
-        # Subscribe to migrate notifications (for updating).
-        id = self.nextid()
-        info = XenMigrateInfo(id, dom, dst)
-        self._add_migrate(id, info)
-        return id
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendMigrate()
-    return inst
diff --git a/tools/xen/lib/xend/XendNode.py b/tools/xen/lib/xend/XendNode.py
deleted file mode 100644 (file)
index 7221785..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Handler for node operations.
- Has some persistent state:
- - logs
- - notification urls
-
-"""
-
-import os
-import xen.ext.xc
-
-class XendNode:
-
-    def __init__(self):
-        self.xc = xen.ext.xc.new()
-
-    def shutdown(self):
-        return 0
-
-    def reboot(self):
-        return 0
-
-    def notify(self, uri):
-        return 0
-    
-    def cpu_bvt_slice_set(self, slice):
-        ret = 0
-        #ret = self.xc.bvtsched_global_set(ctx_allow=slice)
-        return ret
-
-    def cpu_bvt_slice_get(self, slice):
-        ret = 0
-        #ret = self.xc.bvtsched_global_get()
-        return ret
-    
-    def cpu_rrobin_slice_set(self, slice):
-        ret = 0
-        #ret = self.xc.rrobin_global_set(slice)
-        return ret
-
-    def info(self):
-        return self.nodeinfo() + self.physinfo()
-
-    def nodeinfo(self):
-        (sys, host, rel, ver, mch) = os.uname()
-        return [['system',  sys],
-                ['host',    host],
-                ['release', rel],
-                ['version', ver],
-                ['machine', mch]]
-
-    def physinfo(self):
-        pinfo = self.xc.physinfo()
-        info = [['cores', pinfo['cores']],
-                ['hyperthreads_per_core', pinfo['ht_per_core']],
-                ['cpu_mhz', pinfo['cpu_khz']/1000],
-                ['memory', pinfo['total_pages']/256],
-                ['free_memory', pinfo['free_pages']/256]]
-        return info
-        
-        
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendNode()
-    return inst
-
diff --git a/tools/xen/lib/xend/XendRoot.py b/tools/xen/lib/xend/XendRoot.py
deleted file mode 100644 (file)
index 665f5df..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Xend root class.
-Creates the event server and handles configuration.
-"""
-
-import os
-import os.path
-import sys
-import EventServer
-
-# Initial create of the event server.
-eserver = EventServer.instance()
-
-import sxp
-
-def reboots():
-    """Get a list of system reboots from wtmp.
-    """
-    out = os.popen('/usr/bin/last reboot', 'r')
-    list = [ x.strip() for x in out if x.startswith('reboot') ]
-    return list
-
-def last_reboot():
-    """Get the last known system reboot.
-    """
-    l = reboots()
-    return (l and l[-1]) or None
-
-class XendRoot:
-    """Root of the management classes."""
-
-    lastboot_default = "/var/xen/lastboot"
-
-    """Default path to the root of the database."""
-    dbroot_default = "/var/xen/xend-db"
-
-    """Default path to the config file."""
-    config_default = "/etc/xen/xend-config.sxp"
-
-    """Environment variable used to override config_default."""
-    config_var     = "XEND_CONFIG"
-
-    def __init__(self):
-        self.rebooted = 0
-        self.last_reboot = None
-        self.dbroot = None
-        self.config_path = None
-        self.config = None
-        self.configure()
-        self.check_lastboot()
-        eserver.subscribe('xend.*', self.event_handler)
-        #eserver.subscribe('xend.domain.created', self.event_handler)
-        #eserver.subscribe('xend.domain.died', self.event_handler)
-
-    def start(self):
-        eserver.inject('xend.start', self.rebooted)
-
-    def event_handler(self, event, val):
-        print >> sys.stderr, "EVENT>", event, val
-
-    def read_lastboot(self):
-        try:
-            val = file(self.lastboot, 'rb').readlines()[0]
-        except StandardError, ex:
-            print 'warning: Error reading', self.lastboot, ex
-            val = None
-        return val
-
-    def write_lastboot(self, val):
-        if not val: return
-        try:
-            fdir = os.path.dirname(self.lastboot)
-            if not os.path.isdir(fdir):
-                os.makedirs(fdir)
-            out = file(self.lastboot, 'wb+')
-            out.write(val)
-            out.close()
-        except IOError, ex:
-            print 'warning: Error writing', self.lastboot, ex
-            pass
-
-    def check_lastboot(self):
-        """Check if there has been a system reboot since we saved lastboot.
-        """
-        last_val = self.read_lastboot()
-        this_val = last_reboot()
-        if this_val == last_val:
-            self.rebooted = 0
-        else:
-            self.rebooted = 1
-            self.write_lastboot(this_val)
-        self.last_reboot = this_val
-
-    def get_last_reboot(self):
-        return self.last_reboot
-
-    def get_rebooted(self):
-        return self.rebooted
-
-    def configure(self):
-        self.set_config()
-        self.dbroot = self.get_config_value("dbroot", self.dbroot_default)
-        self.lastboot = self.get_config_value("lastboot", self.lastboot_default)
-
-    def get_dbroot(self):
-        """Get the path to the database root.
-        """
-        return self.dbroot
-
-    def set_config(self):
-        """If the config file exists, read it. If not, ignore it.
-
-        The config file is a sequence of sxp forms.
-        """
-        self.config_path = os.getenv(self.config_var, self.config_default)
-        if os.path.exists(self.config_path):
-            fin = file(self.config_path, 'rb')
-            try:
-                config = sxp.parse(fin)
-                config.insert(0, 'config')
-                self.config = config
-            finally:
-                fin.close()
-        else:
-            self.config = ['config']
-
-    def get_config(self, name=None):
-        """Get the configuration element with the given name, or
-        the whole configuration if no name is given.
-
-        name   element name (optional)
-        returns config or none
-        """
-        if name is None:
-            val = self.config
-        else:
-            val = sxp.child(self.config, name)
-        return val
-
-    def get_config_value(self, name, val=None):
-        """Get the value of an atomic configuration element.
-
-        name   element name
-        val    default value (optional, defaults to None)
-        returns value
-        """
-        return sxp.child_value(self.config, name, val=val)
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendRoot()
-    return inst
diff --git a/tools/xen/lib/xend/XendVnet.py b/tools/xen/lib/xend/XendVnet.py
deleted file mode 100644 (file)
index 213408e..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Handler for vnet operations.
-"""
-
-import sxp
-import XendDB
-
-class XendVnet:
-    """Index of all vnets. Singleton.
-    """
-
-    dbpath = "vnet"
-
-    def __init__(self):
-        # Table of vnet info indexed by vnet id.
-        self.vnet = {}
-        self.db = XendDB.XendDB(self.dbpath)
-        self.vnet = self.db.fetchall("")
-
-    def vnet_ls(self):
-        """List all vnets.
-        """
-        return self.vnet.keys()
-
-    def vnets(self):
-        return self.vnet.values()
-
-    def vnet_get(self, id):
-        """Get a vnet.
-
-        id     vnet id
-        """
-        return self.vnet.get(id)
-
-    def vnet_create(self, info):
-        """Create a vnet.
-
-        info   config
-        """
-        self.vnet_configure(info)
-
-    def vnet_configure(self, info):
-        """Configure a vnet.
-        id     vnet id
-        info   config
-        """
-        # Need to configure for real.
-        # Only sync if succeeded - otherwise need to back out.
-        self.vnet[info.id] = info
-        self.db.save(info.id, info)
-
-    def vnet_delete(self, id):
-        """Delete a vnet.
-
-        id     vnet id
-        """
-        # Need to delete for real. What if fails?
-        if id in self.vnet:
-            del self.vnet[id]
-            self.db.delete(id)
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendVnet()
-    return inst
diff --git a/tools/xen/lib/xend/__init__.py b/tools/xen/lib/xend/__init__.py
deleted file mode 100644 (file)
index 8d1c8b6..0000000
+++ /dev/null
@@ -1 +0,0 @@
diff --git a/tools/xen/lib/xend/encode.py b/tools/xen/lib/xend/encode.py
deleted file mode 100644 (file)
index 38c9351..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Encoding for arguments to HTTP calls.
-   Uses the url-encoding with MIME type 'application/x-www-form-urlencoded'
-   if the data does not include files. Otherwise it uses the encoding with
-   MIME type 'multipart/form-data'. See the HTML4 spec for details.
-
-   """
-import sys
-import types
-from StringIO import StringIO
-
-import urllib
-import httplib
-import random
-import md5
-
-# Extract from HTML4 spec.
-## The following example illustrates "multipart/form-data"
-## encoding. Suppose we have the following form:
-
-##  <FORM action="http://server.com/cgi/handle"
-##        enctype="multipart/form-data"
-##        method="post">
-##    <P>
-##    What is your name? <INPUT type="text" name="submit-name"><BR>
-##    What files are you sending? <INPUT type="file" name="files"><BR>
-##    <INPUT type="submit" value="Send"> <INPUT type="reset">
-##  </FORM>
-
-## If the user enters "Larry" in the text input, and selects the text
-## file "file1.txt", the user agent might send back the following data:
-
-##    Content-Type: multipart/form-data; boundary=AaB03x
-
-##    --AaB03x
-##    Content-Disposition: form-data; name="submit-name"
-
-##    Larry
-##    --AaB03x
-##    Content-Disposition: form-data; name="files"; filename="file1.txt"
-##    Content-Type: text/plain
-
-##    ... contents of file1.txt ...
-##    --AaB03x--
-
-## If the user selected a second (image) file "file2.gif", the user agent
-## might construct the parts as follows:
-
-##    Content-Type: multipart/form-data; boundary=AaB03x
-
-##    --AaB03x
-##    Content-Disposition: form-data; name="submit-name"
-
-##    Larry
-##    --AaB03x
-##    Content-Disposition: form-data; name="files"
-##    Content-Type: multipart/mixed; boundary=BbC04y
-
-##    --BbC04y
-##    Content-Disposition: file; filename="file1.txt"
-##    Content-Type: text/plain
-
-##    ... contents of file1.txt ...
-##    --BbC04y
-##    Content-Disposition: file; filename="file2.gif"
-##    Content-Type: image/gif
-##    Content-Transfer-Encoding: binary
-
-##    ...contents of file2.gif...
-##    --BbC04y--
-##    --AaB03x--
-
-__all__ = ['encode_data', 'encode_multipart', 'encode_form', 'mime_boundary' ]
-
-def data_values(d):
-    if isinstance(d, types.DictType):
-        return d.items()
-    else:
-        return d
-
-def encode_data(d):
-    """Encode some data for HTTP transport.
-    The encoding used is stored in 'Content-Type' in the headers.
-
-    d  data - sequence of tuples or dictionary
-    returns a 2-tuple of the headers and the encoded data
-    """
-    val = ({}, None)
-    if d is None: return val
-    multipart = 0
-    for (k, v) in data_values(d):
-        if encode_isfile(v):
-            multipart = 1
-            break
-    if multipart:
-        val = encode_multipart(d)
-    else:
-        val = encode_form(d)
-    return val
-
-def encode_isfile(v):
-    if isinstance(v, types.FileType):
-        return 1
-    if hasattr(v, 'readlines'):
-        return 1
-    return 0
-
-def encode_multipart(d):
-    boundary = mime_boundary()
-    hdr = { 'Content-Type': 'multipart/form-data; boundary=' + boundary }
-    out = StringIO()
-    for (k,v) in data_values(d):
-        out.write('--')
-        out.write(boundary)
-        out.write('\r\n')
-        if encode_isfile(v):
-            out.write('Content-Disposition: form-data; name="')
-            out.write(k)
-            if hasattr(v, 'name'):
-                out.write('"; filename="')
-                out.write(v.name)
-            out.write('"\r\n')
-            out.write('Content-Type: application/octet-stream\r\n')
-            out.write('\r\n')
-            for l in v.readlines():
-               out.write(l)  
-        else:
-            out.write('Content-Disposition: form-data; name="')
-            out.write(k)
-            out.write('"\r\n')
-            out.write('\r\n')
-            out.write(str(v))
-            out.write('\r\n')
-    out.write('--')
-    out.write(boundary)
-    out.write('--')
-    out.write('\r\n')
-    return (hdr, out.getvalue())
-
-def mime_boundary():
-    random.seed()
-    m = md5.new()
-    for i in range(0, 10):
-        c = chr(random.randint(1, 255))
-        m.update(c)
-    b = m.hexdigest()
-    return b[0:16]
-
-def encode_form(d):
-    hdr = { 'Content-Type': 'application/x-www-form-urlencoded' }
-    val = urllib.urlencode(d)
-    return (hdr, val)
-
-def main():
-    #d = {'a': 1, 'b': 'x y', 'c': file('conf.sxp') }
-    #d = {'a': 1, 'b': 'x y' }
-    d = [ ('a', 1), ('b', 'x y'), ('c', file('conf.sxp')) ]
-    #d = [ ('a', 1), ('b', 'x y')]
-    v = encode_data(d)
-    print v[0]
-    sys.stdout.write(v[1])
-    print
-
-if __name__ == "__main__":
-    main()
diff --git a/tools/xen/lib/xend/server/SrvBase.py b/tools/xen/lib/xend/server/SrvBase.py
deleted file mode 100644 (file)
index bcff1bc..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-import cgi
-
-import os
-import sys
-import types
-import StringIO
-
-from twisted.internet import defer
-from twisted.internet import reactor
-from twisted.web import error
-from twisted.web import resource
-from twisted.web import server
-
-from xen.xend import sxp
-from xen.xend import PrettyPrint
-
-def uri_pathlist(p):
-    """Split a path into a list.
-    p          path
-    return list of path elements
-    """
-    l = []
-    for x in p.split('/'):
-        if x == '': continue
-        l.append(x)
-    return l
-
-class SrvBase(resource.Resource):
-    """Base class for services.
-    """
-
-    def parse_form(self, req, method):
-        """Parse the data for a request, GET using the URL, POST using encoded data.
-        Posts should use enctype='multipart/form-data' in the <form> tag,
-        rather than 'application/x-www-form-urlencoded'. Only 'multipart/form-data'
-        handles file upload.
-
-        req            request
-        returns a cgi.FieldStorage instance
-        """
-        env = {}
-        env['REQUEST_METHOD'] = method
-        if self.query:
-            env['QUERY_STRING'] = self.query
-        val = cgi.FieldStorage(fp=req.rfile, headers=req.headers, environ=env)
-        return val
-    
-    def use_sxp(self, req):
-        """Determine whether to send an SXP response to a request.
-        Uses SXP if there is no User-Agent, no Accept, or application/sxp is in Accept.
-
-        req            request
-        returns 1 for SXP, 0 otherwise
-        """
-        ok = 0
-        user_agent = req.getHeader('User-Agent')
-        accept = req.getHeader('Accept')
-        if (not user_agent) or (not accept) or (accept.find(sxp.mime_type) >= 0):
-            ok = 1
-        return ok
-
-    def get_op_method(self, op):
-        """Get the method for an operation.
-        For operation 'foo' looks for 'op_foo'.
-
-        op     operation name
-        returns method or None
-        """
-        op_method_name = 'op_' + op
-        return getattr(self, op_method_name, None)
-        
-    def perform(self, req):
-        """General operation handler for posted operations.
-        For operation 'foo' looks for a method op_foo and calls
-        it with op_foo(op, req). Replies with code 500 if op_foo
-        is not found.
-
-        The method must return a list when req.use_sxp is true
-        and an HTML string otherwise (or list).
-        Methods may also return a Deferred (for incomplete processing).
-
-        req    request
-        """
-        op = req.args.get('op')
-        if op is None or len(op) != 1:
-            req.setResponseCode(404, "Invalid")
-            return ''
-        op = op[0]
-        op_method = self.get_op_method(op)
-        if op_method is None:
-            req.setResponseCode(501, "Not implemented")
-            req.setHeader("Content-Type", "text/plain")
-            req.write("Not implemented: " + op)
-            return ''
-        else:
-            val = op_method(op, req)
-            if isinstance(val, defer.Deferred):
-                val.addCallback(self._cb_perform, req, 1)
-                return server.NOT_DONE_YET
-            else:
-                self._cb_perform(val, req, 0)
-                return ''
-
-    def _cb_perform(self, val, req, dfr):
-        """Callback to complete the request.
-        May be called from a Deferred.
-        """
-        if isinstance(val, error.ErrorPage):
-            req.write(val.render(req))
-        elif self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(val, req)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            if isinstance(val, types.ListType):
-                req.write('<code><pre>')
-                PrettyPrint.prettyprint(val, out=req)
-                req.write('</pre></code>')
-            else:
-                req.write(str(val))
-            req.write('</body></html>')
-        if dfr:
-            req.finish()
-
-    def print_path(self, req):
-        """Print the path with hyperlinks.
-        """
-        pathlist = [x for x in req.prepath if x != '' ]
-        s = "/"
-        req.write('<h1><a href="/">/</a>')
-        for x in pathlist:
-            s += x + "/"
-            req.write(' <a href="%s">%s</a>/' % (s, x))
-        req.write("</h1>")
diff --git a/tools/xen/lib/xend/server/SrvConsole.py b/tools/xen/lib/xend/server/SrvConsole.py
deleted file mode 100644 (file)
index 59d0e5f..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from xen.xend import sxp
-from xen.xend import XendConsole
-from SrvDir import SrvDir
-
-class SrvConsole(SrvDir):
-    """An individual console.
-    """
-
-    def __init__(self, info):
-        SrvDir.__init__(self)
-        self.info = info
-        self.xc = XendConsole.instance()
-
-    def op_disconnect(self, op, req):
-        val = self.xc.console_disconnect(self.info.id)
-        return val
-
-    def render_POST(self, req):
-        return self.perform(req)
-        
-    def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(self.info.sxpr(), out=req)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            #self.ls()
-            req.write('<p>%s</p>' % self.info)
-            req.write('<p><a href="%s">Connect to domain %d</a></p>'
-                      % (self.info.uri(), self.info.dom2))
-            self.form(req)
-            req.write('</body></html>')
-        return ''
-
-    def form(self, req):
-        req.write('<form method="post" action="%s">' % req.prePathURL())
-        if self.info.connection():
-            req.write('<input type="submit" name="op" value="disconnect">')
-        req.write('</form>')
diff --git a/tools/xen/lib/xend/server/SrvConsoleDir.py b/tools/xen/lib/xend/server/SrvConsoleDir.py
deleted file mode 100644 (file)
index 814b448..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from SrvDir import SrvDir
-from SrvConsole import SrvConsole
-from xen.xend import XendConsole
-from xen.xend import sxp
-
-class SrvConsoleDir(SrvDir):
-    """Console directory.
-    """
-
-    def __init__(self):
-        SrvDir.__init__(self)
-        self.xconsole = XendConsole.instance()
-
-    def console(self, x):
-        val = None
-        try:
-            info = self.xconsole.console_get(x)
-            val = SrvConsole(info)
-        except KeyError, ex:
-            print 'SrvConsoleDir>', ex
-            pass
-        return val
-
-    def get(self, x):
-        v = SrvDir.get(self, x)
-        if v is not None:
-            return v
-        v = self.console(x)
-        return v
-
-    def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            self.ls_console(req, 1)
-        else:
-            req.write("<html><head></head><body>")
-            self.print_path(req)
-            self.ls(req)
-            self.ls_console(req)
-            #self.form(req.wfile)
-            req.write("</body></html>")
-        return ''
-
-    def ls_console(self, req, use_sxp=0):
-        url = req.prePathURL()
-        if not url.endswith('/'):
-            url += '/'
-        if use_sxp:
-            consoles = self.xconsole.console_ls()
-            sxp.show(consoles, out=req)
-        else:
-            consoles = self.xconsole.consoles()
-            consoles.sort(lambda x, y: cmp(x.id, y.id))
-            req.write('<ul>')
-            for c in consoles:
-                req.write('<li><a href="%s%s"> %s</a></li>' % (url, c.id, c))
-            req.write('</ul>')
diff --git a/tools/xen/lib/xend/server/SrvDaemon.py b/tools/xen/lib/xend/server/SrvDaemon.py
deleted file mode 100644 (file)
index c8284dc..0000000
+++ /dev/null
@@ -1,751 +0,0 @@
-###########################################################
-## Xen controller daemon
-## Copyright (c) 2004, K A Fraser (University of Cambridge)
-## Copyright (C) 2004, Mike Wray <mike.wray@hp.com>
-###########################################################
-
-import os
-import os.path
-import signal
-import sys
-import threading
-import linecache
-import socket
-import pwd
-import re
-import StringIO
-
-from twisted.internet import pollreactor
-pollreactor.install()
-
-from twisted.internet import reactor
-from twisted.internet import protocol
-from twisted.internet import abstract
-from twisted.internet import defer
-
-from xen.ext import xu
-
-from xen.xend import sxp
-from xen.xend import PrettyPrint
-from xen.xend import EventServer
-eserver = EventServer.instance()
-
-from xen.xend.server import SrvServer
-
-import channel
-import blkif
-import netif
-import console
-import domain
-from params import *
-
-DEBUG = 1
-
-class MgmtProtocol(protocol.DatagramProtocol):
-    """Handler for the management socket (unix-domain).
-    """
-
-    def __init__(self, daemon):
-        #protocol.DatagramProtocol.__init__(self)
-        self.daemon = daemon
-    
-    def write(self, data, addr):
-        return self.transport.write(data, addr)
-
-    def datagramReceived(self, data, addr):
-        if DEBUG: print 'datagramReceived> addr=', addr, 'data=', data
-        io = StringIO.StringIO(data)
-        try:
-            vals = sxp.parse(io)
-            res = self.dispatch(vals[0])
-            self.send_result(addr, res)
-        except SystemExit:
-            raise
-        except:
-            if DEBUG:
-                raise
-            else:
-                self.send_error(addr)
-
-    def send_reply(self, addr, sxpr):
-        io = StringIO.StringIO()
-        sxp.show(sxpr, out=io)
-        io.seek(0)
-        self.write(io.getvalue(), addr)
-
-    def send_result(self, addr, res):
-        
-        def fn(res, self=self, addr=addr):
-            self.send_reply(addr, ['ok', res])
-            
-        if isinstance(res, defer.Deferred):
-            res.addCallback(fn)
-        else:
-            fn(res)
-
-    def send_error(self, addr):
-        (extype, exval) = sys.exc_info()[:2]
-        self.send_reply(addr, ['err',
-                               ['type',  str(extype) ],
-                               ['value', str(exval)  ] ] )
-
-    def opname(self, name):
-        """Get the name of the method for an operation.
-        """
-        return 'op_' + name.replace('.', '_')
-
-    def operror(self, name, v):
-        """Default operation handler - signals an error.
-        """
-        raise NotImplementedError('Invalid operation: ' +name)
-
-    def dispatch(self, req):
-        """Dispatch a request to its handler.
-        """
-        op_name = sxp.name(req)
-        op_method_name = self.opname(op_name)
-        op_method = getattr(self, op_method_name, self.operror)
-        return op_method(op_name, req)
-
-    def op_console_create(self, name, req):
-        """Create a new control interface - console for a domain.
-        """
-        print name, req
-        dom = sxp.child_value(req, 'domain')
-        if not dom: raise ValueError('Missing domain')
-        dom = int(dom)
-        console_port = sxp.child_value(req, 'console_port')
-        if console_port:
-            console_port = int(console_port)
-        resp = self.daemon.console_create(dom, console_port)
-        print name, resp
-        return resp
-
-    def op_consoles(self, name, req):
-        """Get a list of the consoles.
-        """
-        return self.daemon.consoles()
-
-    def op_console_disconnect(self, name, req):
-        id = sxp.child_value(req, 'id')
-        if not id:
-            raise ValueError('Missing console id')
-        id = int(id)
-        console = self.daemon.get_console(id)
-        if not console:
-            raise ValueError('Invalid console id')
-        if console.conn:
-            console.conn.loseConnection()
-        return ['ok']
-
-    def op_blkifs(self, name, req):
-        pass
-    
-    def op_blkif_devs(self, name, req):
-        pass
-
-    def op_blkif_create(self, name, req):
-        pass
-    
-    def op_blkif_dev_create(self, name, req):
-        pass
-
-    def op_netifs(self, name, req):
-        pass
-
-    def op_netif_devs(self, name, req):
-        pass
-
-    def op_netif_create(self, name, req):
-        pass
-
-    def op_netif_dev_create(self, name, req):
-        pass
-
-class NotifierProtocol(protocol.Protocol):
-    """Asynchronous handler for i/o on the notifier (event channel).
-    """
-
-    def __init__(self, channelFactory):
-        self.channelFactory = channelFactory
-
-    def notificationReceived(self, idx, type):
-        #print 'NotifierProtocol>notificationReceived>', idx, type
-        channel = self.channelFactory.getChannel(idx)
-        if not channel:
-            return
-        #print 'NotifierProtocol>notificationReceived> channel', channel
-        channel.notificationReceived(type)
-
-    def connectionLost(self, reason=None):
-        pass
-
-    def doStart(self):
-        pass
-
-    def doStop(self):
-        pass
-
-    def startProtocol(self):
-        pass
-
-    def stopProtocol(self):
-        pass
-
-class NotifierPort(abstract.FileDescriptor):
-    """Transport class for the event channel.
-    """
-
-    def __init__(self, daemon, notifier, proto, reactor=None):
-        assert isinstance(proto, NotifierProtocol)
-        abstract.FileDescriptor.__init__(self, reactor)
-        self.daemon = daemon
-        self.notifier = notifier
-        self.protocol = proto
-
-    def startListening(self):
-        self._bindNotifier()
-        self._connectToProtocol()
-
-    def stopListening(self):
-        if self.connected:
-            result = self.d = defer.Deferred()
-        else:
-            result = None
-        self.loseConnection()
-        return result
-
-    def fileno(self):
-        return self.notifier.fileno()
-
-    def _bindNotifier(self):
-        self.connected = 1
-
-    def _connectToProtocol(self):
-        self.protocol.makeConnection(self)
-        self.startReading()
-
-    def loseConnection(self):
-        if self.connected:
-            self.stopReading()
-            self.disconnecting = 1
-            reactor.callLater(0, self.connectionLost)
-
-    def connectionLost(self, reason=None):
-        abstract.FileDescriptor.connectionLost(self, reason)
-        if hasattr(self, 'protocol'):
-            self.protocol.doStop()
-        self.connected = 0
-        #self.notifier.close() # Not implemented.
-        os.close(self.fileno())
-        del self.notifier
-        if hasattr(self, 'd'):
-            self.d.callback(None)
-            del self.d
-        
-    def doRead(self):
-        #print 'NotifierPort>doRead>', self
-        count = 0
-        while 1:            
-            #print 'NotifierPort>doRead>', count
-            notification = self.notifier.read()
-            if not notification:
-                break
-            (idx, type) = notification
-            self.protocol.notificationReceived(idx, type)
-            self.notifier.unmask(idx)
-            count += 1
-        #print 'NotifierPort>doRead<'
-
-class EventProtocol(protocol.Protocol):
-    """Asynchronous handler for a connected event socket.
-    """
-
-    def __init__(self, daemon):
-        #protocol.Protocol.__init__(self)
-        self.daemon = daemon
-        # Event queue.
-        self.queue = []
-        # Subscribed events.
-        self.events = []
-        self.parser = sxp.Parser()
-        self.pretty = 0
-
-        # For debugging subscribe to everything and make output pretty.
-        self.subscribe(['*'])
-        self.pretty = 1
-
-    def dataReceived(self, data):
-        try:
-            self.parser.input(data)
-            if self.parser.ready():
-                val = self.parser.get_val()
-                res = self.dispatch(val)
-                self.send_result(res)
-            if self.parser.at_eof():
-                self.loseConnection()
-        except SystemExit:
-            raise
-        except:
-            if DEBUG:
-                raise
-            else:
-                self.send_error()
-
-    def loseConnection(self):
-        if self.transport:
-            self.transport.loseConnection()
-        if self.connected:
-            reactor.callLater(0, self.connectionLost)
-
-    def connectionLost(self, reason=None):
-        self.unsubscribe()
-
-    def send_reply(self, sxpr):
-        io = StringIO.StringIO()
-        if self.pretty:
-            PrettyPrint.prettyprint(sxpr, out=io)
-        else:
-            sxp.show(sxpr, out=io)
-        print >> io
-        io.seek(0)
-        return self.transport.write(io.getvalue())
-
-    def send_result(self, res):
-        return self.send_reply(['ok', res])
-
-    def send_error(self):
-        (extype, exval) = sys.exc_info()[:2]
-        return self.send_reply(['err',
-                                ['type', str(extype)],
-                                ['value', str(exval)]])
-
-    def send_event(self, val):
-        return self.send_reply(['event', val[0], val[1]])
-
-    def unsubscribe(self):
-        for event in self.events:
-            eserver.unsubscribe(event, self.queue_event)
-
-    def subscribe(self, events):
-        self.unsubscribe()
-        for event in events:
-            eserver.subscribe(event, self.queue_event)
-        self.events = events
-
-    def queue_event(self, name, v):
-        # Despite the name we dont' queue the event here.
-        # We send it because the transport will queue it.
-        self.send_event([name, v])
-        
-    def opname(self, name):
-         return 'op_' + name.replace('.', '_')
-
-    def operror(self, name, req):
-        raise NotImplementedError('Invalid operation: ' +name)
-
-    def dispatch(self, req):
-        op_name = sxp.name(req)
-        op_method_name = self.opname(op_name)
-        op_method = getattr(self, op_method_name, self.operror)
-        return op_method(op_name, req)
-
-    def op_help(self, name, req):
-        def nameop(x):
-            if x.startswith('op_'):
-                return x[3:].replace('_', '.')
-            else:
-                return x
-        
-        l = [ nameop(k) for k in dir(self) if k.startswith('op_') ]
-        return l
-
-    def op_quit(self, name, req):
-        self.loseConnection()
-
-    def op_exit(self, name, req):
-        sys.exit(0)
-
-    def op_pretty(self, name, req):
-        self.pretty = 1
-        return ['ok']
-
-    def op_console_disconnect(self, name, req):
-        id = sxp.child_value(req, 'id')
-        if not id:
-            raise ValueError('Missing console id')
-        self.daemon.console_disconnect(id)
-        return ['ok']
-
-    def op_info(self, name, req):
-        val = ['info']
-        val += self.daemon.consoles()
-        val += self.daemon.blkifs()
-        val += self.daemon.netifs()
-        return val
-
-    def op_sys_subscribe(self, name, v):
-        # (sys.subscribe event*)
-        # Subscribe to the events:
-        self.subscribe(v[1:])
-        return ['ok']
-
-    def op_sys_inject(self, name, v):
-        # (sys.inject event)
-        event = v[1]
-        eserver.inject(sxp.name(event), event)
-        return ['ok']
-
-
-class EventFactory(protocol.Factory):
-    """Asynchronous handler for the event server socket.
-    """
-    protocol = EventProtocol
-    service = None
-
-    def __init__(self, daemon):
-        #protocol.Factory.__init__(self)
-        self.daemon = daemon
-
-    def buildProtocol(self, addr):
-        proto = self.protocol(self.daemon)
-        proto.factory = self
-        return proto
-
-class VirqClient:
-    def __init__(self, daemon):
-        self.daemon = daemon
-
-    def virqReceived(self, virq):
-        print 'VirqClient.virqReceived>', virq
-        eserver.inject('xend.virq', virq)
-
-    def lostChannel(self, channel):
-        print 'VirqClient.lostChannel>', channel
-        
-class Daemon:
-    """The xend daemon.
-    """
-    def __init__(self):
-        self.shutdown = 0
-
-    def daemon_pids(self):
-        pids = []
-        pidex = '(?P<pid>\d+)'
-        pythonex = '(?P<python>\S*python\S*)'
-        cmdex = '(?P<cmd>.*)'
-        procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
-        xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
-        procs = os.popen('ps -e -o pid,args 2>/dev/null')
-        for proc in procs:
-            pm = procre.match(proc)
-            if not pm: continue
-            xm = xendre.match(pm.group('cmd'))
-            if not xm: continue
-            #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
-            pids.append(int(pm.group('pid')))
-        return pids
-
-    def new_cleanup(self, kill=0):
-        err = 0
-        pids = self.daemon_pids()
-        if kill:
-            for pid in pids:
-                print "Killing daemon pid=%d" % pid
-                os.kill(pid, signal.SIGHUP)
-        elif pids:
-            err = 1
-            print "Daemon already running: ", pids
-        return err
-            
-    def cleanup(self, kill=False):
-        # No cleanup to do if PID_FILE is empty.
-        if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
-            return 0
-        # Read the pid of the previous invocation and search active process list.
-        pid = open(PID_FILE, 'r').read()
-        lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
-        for line in lines:
-            if re.search('^ *' + pid + '.+xend', line):
-                if not kill:
-                    print "Daemon is already running (pid %d)" % int(pid)
-                    return 1
-                # Old daemon is still active: terminate it.
-                os.kill(int(pid), 1)
-        # Delete the stale PID_FILE.
-        os.remove(PID_FILE)
-        return 0
-
-    def install_child_reaper(self):
-        #signal.signal(signal.SIGCHLD, self.onSIGCHLD)
-        # Ensure that zombie children are automatically reaped.
-        xu.autoreap()
-
-    def onSIGCHLD(self, signum, frame):
-        code = 1
-        while code > 0:
-            code = os.waitpid(-1, os.WNOHANG)
-
-    def start(self,trace=0):
-        if self.cleanup(kill=False):
-            return 1
-
-        # Detach from TTY.
-        if not DEBUG:
-            os.setsid()
-
-        if self.set_user():
-            return 1
-
-        self.install_child_reaper()
-
-        # Fork -- parent writes PID_FILE and exits.
-        pid = os.fork()
-        if pid:
-            # Parent
-            pidfile = open(PID_FILE, 'w')
-            pidfile.write(str(pid))
-            pidfile.close()
-            return 0
-        # Child
-        logfile = self.open_logfile()
-        self.redirect_output(logfile)
-        if trace:
-            self.tracefile = open('/var/log/xend.trace', 'w+', 1)
-            self.traceindent = 0
-            sys.settrace(self.trace)
-            try:
-                threading.settrace(self.trace) # Only in Python >= 2.3
-            except:
-                pass
-        self.run()
-        return 0
-
-    def print_trace(self,str):
-        for i in range(self.traceindent):
-            self.tracefile.write("    ")
-        self.tracefile.write(str)
-            
-    def trace(self, frame, event, arg):
-        if event == 'call':
-            code = frame.f_code
-            filename = code.co_filename
-            m = re.search('.*xenmgr/(.*)', code.co_filename)
-            if not m:
-                return None
-            modulename = m.group(1)
-            if re.search('sxp.py', modulename):
-                return None
-            self.traceindent += 1
-            self.print_trace("++++ %s:%s\n"
-                             % (modulename, code.co_name))
-        elif event == 'line':
-            filename = frame.f_code.co_filename
-            lineno = frame.f_lineno
-            self.print_trace("%4d %s" %
-                             (lineno, linecache.getline(filename, lineno)))
-        elif event == 'return':
-            code = frame.f_code
-            filename = code.co_filename
-            m = re.search('.*xenmgr/(.*)', code.co_filename)
-            if not m:
-                return None
-            modulename = m.group(1)
-            self.print_trace("---- %s:%s\n"
-                             % (modulename, code.co_name))
-            self.traceindent -= 1
-        elif event == 'exception':
-            pass
-        return self.trace
-
-    def open_logfile(self):
-        if not os.path.exists(CONTROL_DIR):
-            os.makedirs(CONTROL_DIR)
-
-        # Open log file. Truncate it if non-empty, and request line buffering.
-        if os.path.isfile(LOG_FILE):
-            os.rename(LOG_FILE, LOG_FILE+'.old')
-        logfile = open(LOG_FILE, 'w+', 1)
-        return logfile
-
-    def set_user(self):
-        # Set the UID.
-        try:
-            os.setuid(pwd.getpwnam(USER)[2])
-            return 0
-        except KeyError, error:
-            print "Error: no such user '%s'" % USER
-            return 1
-
-    def redirect_output(self, logfile):
-        if DEBUG: return
-        # Close down standard file handles
-        try:
-            os.close(0) # stdin
-            os.close(1) # stdout
-            os.close(2) # stderr
-        except:
-            pass
-        # Redirect output to log file.
-        sys.stdout = sys.stderr = logfile
-
-    def stop(self):
-        return self.cleanup(kill=True)
-
-    def run(self):
-        self.createFactories()
-        self.listenMgmt()
-        self.listenEvent()
-        self.listenNotifier()
-        self.listenVirq()
-        SrvServer.create(bridge=1)
-        reactor.run()
-
-    def createFactories(self):
-        self.channelF = channel.channelFactory()
-        self.domainCF = domain.DomainControllerFactory()
-        self.blkifCF = blkif.BlkifControllerFactory()
-        self.netifCF = netif.NetifControllerFactory()
-        self.consoleCF = console.ConsoleControllerFactory()
-
-    def listenMgmt(self):
-        protocol = MgmtProtocol(self)
-        s = os.path.join(CONTROL_DIR, MGMT_SOCK)
-        if os.path.exists(s):
-            os.unlink(s)
-        return reactor.listenUNIXDatagram(s, protocol)
-
-    def listenEvent(self):
-        protocol = EventFactory(self)
-        return reactor.listenTCP(EVENT_PORT, protocol)
-
-    def listenNotifier(self):
-        protocol = NotifierProtocol(self.channelF)
-        p = NotifierPort(self, self.channelF.notifier, protocol, reactor)
-        p.startListening()
-        return p
-
-    def listenVirq(self):
-        virqChan = self.channelF.virqChannel(channel.VIRQ_DOM_EXC)
-        virqChan.registerClient(VirqClient(self))
-
-    def exit(self):
-        reactor.diconnectAll()
-        sys.exit(0)
-
-    def blkif_set_control_domain(self, dom, recreate=0):
-        """Set the block device backend control domain.
-        """
-        return self.blkifCF.setControlDomain(dom, recreate=recreate)
-    
-    def blkif_get_control_domain(self, dom):
-        """Get the block device backend control domain.
-        """
-        return self.blkifCF.getControlDomain()
-    
-    def blkif_create(self, dom, recreate=0):
-        """Create a block device interface controller.
-        
-        Returns Deferred
-        """
-        d = self.blkifCF.createInstance(dom, recreate=recreate)
-        return d
-
-    def blkifs(self):
-        return [ x.sxpr() for x in self.blkifCF.getInstances() ]
-
-    def blkif_get(self, dom):
-        return self.blkifCF.getInstanceByDom(dom)
-
-    def blkif_dev(self, dom, vdev):
-        return self.blkifCF.getDomainDevice(dom, vdev)
-
-    def blkif_dev_create(self, dom, vdev, mode, segment, recreate=0):
-        """Create a block device.
-        
-        Returns Deferred
-        """
-        ctrl = self.blkifCF.getInstanceByDom(dom)
-        if not ctrl:
-            raise ValueError('No blkif controller: %d' % dom)
-        print 'blkif_dev_create>', dom, vdev, mode, segment
-        d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate)
-        return d
-
-    def netif_set_control_domain(self, dom, recreate=0):
-        """Set the network interface backend control domain.
-        """
-        return self.netifCF.setControlDomain(dom, recreate=recreate)
-
-    def netif_get_control_domain(self, dom):
-        """Get the network interface backend control domain.
-        """
-        return self.netifCF.getControlDomain()
-    
-    def netif_create(self, dom, recreate=0):
-        """Create a network interface controller.
-        
-        """
-        return self.netifCF.createInstance(dom, recreate=recreate)
-
-    def netifs(self):
-        return [ x.sxpr() for x in self.netifCF.getInstances() ]
-
-    def netif_get(self, dom):
-        return self.netifCF.getInstanceByDom(dom)
-
-    def netif_dev_create(self, dom, vif, vmac, recreate=0):
-        """Create a network device.
-
-        todo
-        """
-        ctrl = self.netifCF.getInstanceByDom(dom)
-        if not ctrl:
-            raise ValueError('No netif controller: %d' % dom)
-        d = ctrl.attachDevice(vif, vmac, recreate=recreate)
-        return d
-
-    def netif_dev(self, dom, vif):
-        return self.netifCF.getDomainDevice(dom, vif)
-
-    def console_create(self, dom, console_port=None):
-        """Create a console for a domain.
-        """
-        console = self.consoleCF.getInstanceByDom(dom)
-        if console is None:
-            console = self.consoleCF.createInstance(dom, console_port)
-        return console.sxpr()
-
-    def consoles(self):
-        return [ c.sxpr() for c in self.consoleCF.getInstances() ]
-
-    def get_console(self, id):
-        return self.consoleCF.getInstance(id)
-
-    def get_domain_console(self, dom):
-        return self.consoleCF.getInstanceByDom(dom)
-
-    def console_disconnect(self, id):
-        """Disconnect any connected console client.
-        """
-        console = self.get_console(id)
-        if not console:
-            raise ValueError('Invalid console id')
-        console.disconnect()
-
-    def domain_shutdown(self, dom, reason):
-        """Shutdown a domain.
-        """
-        ctrl = self.domainCF.getInstanceByDom(dom)
-        if not ctrl:
-            raise ValueError('No domain controller: %d' % dom)
-        ctrl.shutdown(reason)
-        return 0
-        
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = Daemon()
-    return inst
diff --git a/tools/xen/lib/xend/server/SrvDeviceDir.py b/tools/xen/lib/xend/server/SrvDeviceDir.py
deleted file mode 100644 (file)
index 52f4285..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from SrvDir import SrvDir
-
-class SrvDeviceDir(SrvDir):
-    """Device directory.
-    """
-
-    pass
diff --git a/tools/xen/lib/xend/server/SrvDir.py b/tools/xen/lib/xend/server/SrvDir.py
deleted file mode 100644 (file)
index c49c0b3..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from twisted.web import error
-from xen.xend import sxp
-from SrvBase import SrvBase
-
-class SrvConstructor:
-    """Delayed constructor for sub-servers.
-    Does not import the sub-server class or create the object until needed.
-    """
-    
-    def __init__(self, klass):
-        """Create a constructor. It is assumed that the class
-        should be imported as 'import klass from klass'.
-
-        klass  name of its class
-        """
-        self.klass = klass
-        self.obj = None
-
-    def getobj(self):
-        """Get the sub-server object, importing its class and instantiating it if
-        necessary.
-        """
-        if not self.obj:
-            exec 'from %s import %s' % (self.klass, self.klass)
-            klassobj = eval(self.klass)
-            self.obj = klassobj()
-        return self.obj
-
-class SrvDir(SrvBase):
-    """Base class for directory servlets.
-    """
-    isLeaf = False
-    
-    def __init__(self):
-        SrvBase.__init__(self)
-        self.table = {}
-        self.order = []
-
-    def getChild(self, x, req):
-        if x == '': return self
-        val = self.get(x)
-        if val is None:
-            return error.NoResource('Not found')
-        else:
-            return val
-
-    def get(self, x):
-        val = self.table.get(x)
-        if val is not None:
-            val = val.getobj()
-        return val
-
-    def add(self, x, xclass = None):
-        if xclass is None:
-            xclass = 'SrvDir'
-        self.table[x] = SrvConstructor(xclass)
-        self.order.append(x)
-
-    def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-type", sxp.mime_type)
-            self.ls(req, 1)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            self.ls(req)
-            self.form(req)
-            req.write('</body></html>')
-        return ''
-            
-    def ls(self, req, use_sxp=0):
-        url = req.prePathURL()
-        if not url.endswith('/'):
-            url += '/'
-        if use_sxp:
-           req.write('(ls ')
-           for k in self.order:
-               req.write(' ' + k)
-           req.write(')')
-        else:
-            req.write('<ul>')
-            for k in self.order:
-                v = self.get(k)
-                req.write('<li><a href="%s%s">%s</a></li>'
-                          % (url, k, k))
-            req.write('</ul>')
-
-    def form(self, req):
-        pass
diff --git a/tools/xen/lib/xend/server/SrvDomain.py b/tools/xen/lib/xend/server/SrvDomain.py
deleted file mode 100644 (file)
index 156198b..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from xen.xend import sxp
-from xen.xend import XendDomain
-from xen.xend import XendConsole
-from xen.xend import PrettyPrint
-from xen.xend.Args import FormFn
-
-from SrvDir import SrvDir
-
-class SrvDomain(SrvDir):
-    """Service managing a single domain.
-    """
-
-    def __init__(self, dom):
-        SrvDir.__init__(self)
-        self.dom = dom
-        self.xd = XendDomain.instance()
-        self.xconsole = XendConsole.instance()
-
-    def op_unpause(self, op, req):
-        val = self.xd.domain_unpause(self.dom.id)
-        return val
-        
-    def op_pause(self, op, req):
-        val = self.xd.domain_pause(self.dom.id)
-        return val
-
-    def op_shutdown(self, op, req):
-        val = self.xd.domain_shutdown(self.dom.id)
-        req.setResponseCode(202)
-        req.setHeader("Location", "%s/.." % req.prePathURL())
-        return val
-
-    def op_destroy(self, op, req):
-        val = self.xd.domain_destroy(self.dom.id)
-        req.setHeader("Location", "%s/.." % req.prePathURL())
-        return val
-
-    def op_save(self, op, req):
-        fn = FormFn(self.xd.domain_save,
-                    [['dom', 'int'],
-                     ['file', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_migrate(self, op, req):
-        fn = FormFn(self.xd.domain_migrate,
-                    [['dom', 'int'],
-                     ['destination', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        val = 0 # Some migrate id.
-        req.setResponseCode(202)
-        #req.send_header("Location", "%s/.." % self.path) # Some migrate url.
-        return val
-
-    def op_pincpu(self, op, req):
-        fn = FormFn(self.xd.domain_pincpu,
-                    [['dom', 'int'],
-                     ['cpu', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_cpu_bvt_set(self, op, req):
-        fn = FormFn(self.xd.domain_cpu_bvt_set,
-                    [['dom', 'int'],
-                     ['mcuadv', 'int'],
-                     ['warp', 'int'],
-                     ['warpl', 'int'],
-                     ['warpu', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_cpu_atropos_set(self, op, req):
-        fn = FormFn(self.xd.domain_cpu_atropos_set,
-                    [['dom', 'int'],
-                     ['period', 'int'],
-                     ['slice', 'int'],
-                     ['latency', 'int'],
-                     ['xtratime', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vifs(self, op, req):
-        return self.xd.domain_vif_ls(self.dom.id)
-
-    def op_vif(self, op, req):
-        fn = FormFn(self.xd.domain_vif_get,
-                    [['dom', 'int'],
-                     ['vif', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vif_stats(self, op, req):
-        #todo
-        fn = FormFn(self.xd.domain_vif_stats,
-                    [['dom', 'int'],
-                     ['vif', 'int']])
-        #val = fn(req.args, {'dom': self.dom.id})
-        val = 999
-        #return val
-        return val
-
-    def op_vif_ip_add(self, op, req):
-        fn = FormFn(self.xd.domain_vif_ip_add,
-                    [['dom', 'int'],
-                     ['vif', 'int'],
-                     ['ip', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vif_scheduler_set(self, op, req):
-        fn = FormFn(self.xd.domain_vif_scheduler_set,
-                    [['dom', 'int'],
-                     ['vif', 'int'],
-                     ['bytes', 'int'],
-                     ['usecs', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vif_scheduler_get(self, op, req):
-        fn = FormFn(self.xd.domain_vif_scheduler_set,
-                    [['dom', 'int'],
-                     ['vif', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vbds(self, op, req):
-        return self.xd.domain_vbd_ls(self.dom.id)
-
-    def op_vbd(self, op, req):
-        fn = FormFn(self.xd.domain_vbd_get,
-                    [['dom', 'int'],
-                     ['vbd', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vbd_add(self, op, req):
-        fn = FormFn(self.xd.domain_vbd_add,
-                    [['dom', 'int'],
-                     ['uname', 'str'],
-                     ['dev', 'str'],
-                     ['mode', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vbd_remove(self, op, req):
-        fn = FormFn(self.xd.domain_vbd_remove,
-                    [['dom', 'int'],
-                     ['dev', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def render_POST(self, req):
-        return self.perform(req)
-        
-    def render_GET(self, req):
-        op = req.args.get('op')
-        if op and op[0] in ['vifs', 'vif', 'vif_stats', 'vbds', 'vbd']:
-            return self.perform(req)
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(self.dom.sxpr(), out=req)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            #self.ls()
-            req.write('<p>%s</p>' % self.dom)
-            if self.dom.console:
-                cinfo = self.dom.console
-                cid = cinfo.id
-                #todo: Local xref: need to know server prefix.
-                req.write('<p><a href="/xend/console/%s">Console %s</a></p>'
-                          % (cid, cid))
-                req.write('<p><a href="%s">Connect to console</a></p>'
-                          % cinfo.uri())
-            if self.dom.config:
-                req.write("<code><pre>")
-                PrettyPrint.prettyprint(self.dom.config, out=req)
-                req.write("</pre></code>")
-            req.write('<a href="%s?op=vif_stats&vif=0">vif 0 stats</a>'
-                      % req.prePathURL())
-            self.form(req)
-            req.write('</body></html>')
-        return ''
-
-    def form(self, req):
-        req.write('<form method="post" action="%s">' % req.prePathURL())
-        req.write('<input type="submit" name="op" value="unpause">')
-        req.write('<input type="submit" name="op" value="pause">')
-        req.write('<input type="submit" name="op" value="shutdown">')
-        req.write('<input type="submit" name="op" value="destroy">')
-        req.write('<br><input type="submit" name="op" value="migrate">')
-        req.write('To: <input type="text" name="destination">')
-        req.write('</form>')
diff --git a/tools/xen/lib/xend/server/SrvDomainDir.py b/tools/xen/lib/xend/server/SrvDomainDir.py
deleted file mode 100644 (file)
index af4bc7a..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from StringIO import StringIO
-
-from twisted.protocols import http
-from twisted.web import error
-
-from xen.xend import sxp
-from xen.xend import XendDomain
-from xen.xend.Args import FormFn
-
-from SrvDir import SrvDir
-from SrvDomain import SrvDomain
-
-class SrvDomainDir(SrvDir):
-    """Service that manages the domain directory.
-    """
-
-    def __init__(self):
-        SrvDir.__init__(self)
-        self.xd = XendDomain.instance()
-
-    def domain(self, x):
-        val = None
-        try:
-            dom = self.xd.domain_get(x)
-            val = SrvDomain(dom)
-        except KeyError, ex:
-            print 'SrvDomainDir>', ex
-            pass
-        return val
-
-    def get(self, x):
-        v = SrvDir.get(self, x)
-        if v is not None:
-            return v
-        v = self.domain(x)
-        return v
-
-    def op_create(self, op, req):
-        ok = 0
-        try:
-            configstring = req.args.get('config')[0]
-            print 'config:', configstring
-            pin = sxp.Parser()
-            pin.input(configstring)
-            pin.input_eof()
-            config = pin.get_val()
-            ok = 1
-        except Exception, ex:
-            print 'op_create>', ex
-        if not ok:
-            req.setResponseCode(http.BAD_REQUEST, "Invalid configuration")
-            return "Invalid configuration"
-            return error.ErrorPage(http.BAD_REQUEST,
-                                   "Invalid",
-                                   "Invalid configuration")
-        try:
-            deferred = self.xd.domain_create(config)
-            deferred.addCallback(self._cb_op_create, configstring, req)
-            return deferred
-        except Exception, ex:
-            raise
-            #return ['err', str(ex) ]
-            #req.setResponseCode(http.BAD_REQUEST, "Error creating domain")
-            #return str(ex)
-            #return error.ErrorPage(http.BAD_REQUEST,
-            #                       "Error creating domain",
-            #                       str(ex))
-                                   
-
-    def _cb_op_create(self, dominfo, configstring, req):
-        """Callback to handle deferred domain creation.
-        """
-        dom = dominfo.id
-        domurl = "%s/%s" % (req.prePathURL(), dom)
-        req.setResponseCode(201, "created")
-        req.setHeader("Location", domurl)
-        if self.use_sxp(req):
-            return dominfo.sxpr()
-        else:
-            out = StringIO()
-            print >> out, ('<p> Created <a href="%s">Domain %s</a></p>'
-                           % (domurl, dom))
-            print >> out, '<p><pre>'
-            print >> out, configstring
-            print >> out, '</pre></p>'
-            val = out.getvalue()
-            out.close()
-            return val
-
-    def op_restore(self, op, req):
-        fn = FormFn(self.xd.domain_restore,
-                    [['file', 'str']])
-        val = fn(req.args)
-        return val
-        
-    def render_POST(self, req):
-        return self.perform(req)
-
-    def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            self.ls_domain(req, 1)
-        else:
-            req.write("<html><head></head><body>")
-            self.print_path(req)
-            self.ls(req)
-            self.ls_domain(req)
-            self.form(req)
-            req.write("</body></html>")
-        return ''
-
-    def ls_domain(self, req, use_sxp=0):
-        url = req.prePathURL()
-        if not url.endswith('/'):
-            url += '/'
-        if use_sxp:
-            domains = self.xd.domain_ls()
-            sxp.show(domains, out=req)
-        else:
-            domains = self.xd.domains()
-            domains.sort(lambda x, y: cmp(x.id, y.id))
-            req.write('<ul>')
-            for d in domains:
-               req.write('<li><a href="%s%s"> Domain %s</a>'
-                         % (url, d.id, d.id))
-               req.write('name=%s' % d.name)
-               req.write('memory=%d'% d.memory)
-               req.write('</li>')
-            req.write('</ul>')
-
-    def form(self, req):
-        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
-                  % req.prePathURL())
-        req.write('<button type="submit" name="op" value="create">Create Domain</button>')
-        req.write('Config <input type="file" name="config"><br>')
-        req.write('</form>')
-        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
-                  % req.prePathURL())
-        req.write('<button type="submit" name="op" value="create">Restore Domain</button>')
-        req.write('State <input type="string" name="state"><br>')
-        req.write('</form>')
-        
diff --git a/tools/xen/lib/xend/server/SrvEventDir.py b/tools/xen/lib/xend/server/SrvEventDir.py
deleted file mode 100644 (file)
index 02871a4..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from xen.xend import sxp
-from xen.xend import EventServer
-from SrvDir import SrvDir
-
-class SrvEventDir(SrvDir):
-    """Event directory.
-    """
-
-    def __init__(self):
-        SrvDir.__init__(self)
-        self.eserver = EventServer.instance()
-
-    def op_inject(self, op, req):
-        eventstring = req.args.get('event')
-        pin = sxp.Parser()
-        pin.input(eventstring)
-        pin.input_eof()
-        sxpr = pin.get_val()
-        self.eserver.inject(sxp.name(sxpr), sxpr)
-        if req.use_sxp:
-            sxp.name(sxpr)
-        else:
-            return '<code>' + eventstring + '</code>'
-        
-    def render_POST(self, req):
-        return self.perform(req)
-
-    def form(self, req):
-        action = req.prePathURL()
-        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
-                  % action)
-        req.write('<button type="submit" name="op" value="inject">Inject</button>')
-        req.write('Event <input type="text" name="event" size="40"><br>')
-        req.write('</form>')
-        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
-                  % action)
-        req.write('<button type="submit" name="op" value="inject">Inject</button>')
-        req.write('Event file<input type="file" name="event"><br>')
-        req.write('</form>')
diff --git a/tools/xen/lib/xend/server/SrvNode.py b/tools/xen/lib/xend/server/SrvNode.py
deleted file mode 100644 (file)
index 69747d8..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-import os
-from SrvDir import SrvDir
-from xen.xend import sxp
-from xen.xend import XendNode
-
-class SrvNode(SrvDir):
-    """Information about the node.
-    """
-
-    def __init__(self):
-        SrvDir.__init__(self)
-        self.xn = XendNode.instance()
-
-    def op_shutdown(self, op, req):
-        val = self.xn.shutdown()
-        return val
-
-    def op_reboot(self, op, req):
-        val = self.xn.reboot()
-        return val
-
-    def op_cpu_rrobin_slice_set(self, op, req):
-        fn = FormFn(self.xn.cpu_rrobin_slice_set,
-                    [['slice', 'int']])
-        val = fn(req.args, {})
-        return val
-
-    def op_cpu_bvt_slice_set(self, op, req):
-        fn = FormFn(self.xn.cpu_bvt_slice_set,
-                    [['slice', 'int']])
-        val = fn(req.args, {})
-        return val
-
-    def render_POST(self, req):
-        return self.perform(req)
-
-    def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(['node'] + self.info(), out=req)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            req.write('<ul>')
-            for d in self.info():
-                req.write('<li> %10s: %s' % (d[0], str(d[1])))
-            req.write('</ul>')
-            req.write('</body></html>')
-        return ''
-            
-    def info(self):
-        return self.xn.info()
diff --git a/tools/xen/lib/xend/server/SrvRoot.py b/tools/xen/lib/xend/server/SrvRoot.py
deleted file mode 100644 (file)
index 8d38937..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from xen.xend import XendRoot
-xroot = XendRoot.instance()
-from SrvDir import SrvDir
-
-class SrvRoot(SrvDir):
-    """The root of the xend server.
-    """
-
-    """Server sub-components. Each entry is (name, class), where
-    'name' is the entry name and  'class' is the name of its class.
-    """
-    #todo Get this list from the XendRoot config.
-    subdirs = [
-        ('node',    'SrvNode'       ),
-        ('domain',  'SrvDomainDir'  ),
-        ('console', 'SrvConsoleDir' ),
-        ('event',   'SrvEventDir'   ),
-        ('device',  'SrvDeviceDir'  ),
-        ('vnet',    'SrvVnetDir'    ),
-        ]
-
-    def __init__(self):
-        SrvDir.__init__(self)
-        for (name, klass) in self.subdirs:
-            self.add(name, klass)
-        for (name, klass) in self.subdirs:
-            self.get(name)
-        xroot.start()
diff --git a/tools/xen/lib/xend/server/SrvServer.py b/tools/xen/lib/xend/server/SrvServer.py
deleted file mode 100644 (file)
index ac201dd..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/python2
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Example xend HTTP and console server.
-
-   Can be accessed from a browser or from a program.
-   Do 'python SrvServer.py' to run the server.
-   Then point a web browser at http://localhost:8000/xend and follow the links.
-   Most are stubs, except /domain which has a list of domains and a 'create domain'
-   button.
-
-   You can also access the server from a program.
-   Do 'python XendClient.py' to run a few test operations.
-
-   The data served differs depending on the client (as defined by User-Agent
-   and Accept in the HTTP headers). If the client is a browser, data
-   is returned in HTML, with interactive forms. If the client is a program,
-   data is returned in SXP format, with no forms.
-
-   The server serves to the world by default. To restrict it to the local host
-   change 'interface' in main().
-
-   Mike Wray <mike.wray@hp.com>
-"""
-# todo Support security settings etc. in the config file.
-# todo Support command-line args.
-
-from twisted.web import server
-from twisted.web import resource
-from twisted.internet import reactor
-
-from xen.xend import XendRoot
-xroot = XendRoot.instance()
-
-from xen.xend import Vifctl
-
-from SrvRoot import SrvRoot
-
-def create(port=None, interface=None, bridge=0):
-    if port is None: port = 8000
-    if interface is None: interface = ''
-    if bridge or xroot.rebooted:
-        init_bridge()
-    root = resource.Resource()
-    xend = SrvRoot()
-    root.putChild('xend', xend)
-    site = server.Site(root)
-    reactor.listenTCP(port, site, interface=interface)
-
-def init_bridge():
-    Vifctl.init()
-
-def main(port=None, interface=None):
-    create(port, interface)
-    reactor.run()
-
-
-if __name__ == '__main__':
-    main()
diff --git a/tools/xen/lib/xend/server/SrvVnetDir.py b/tools/xen/lib/xend/server/SrvVnetDir.py
deleted file mode 100644 (file)
index a8a8141..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from SrvDir import SrvDir
-
-class SrvVnetDir(SrvDir):
-    """Vnet directory.
-    """
-
-    pass
diff --git a/tools/xen/lib/xend/server/__init__.py b/tools/xen/lib/xend/server/__init__.py
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tools/xen/lib/xend/server/blkif.py b/tools/xen/lib/xend/server/blkif.py
deleted file mode 100755 (executable)
index 4e2a49f..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-from twisted.internet import defer
-
-from xen.xend import sxp
-from xen.xend import PrettyPrint
-
-import channel
-import controller
-from messages import *
-
-class BlkifControllerFactory(controller.ControllerFactory):
-    """Factory for creating block device interface controllers.
-    Also handles the 'back-end' channel to the device driver domain.
-    """
-
-    def __init__(self):
-        controller.ControllerFactory.__init__(self)
-
-        self.majorTypes = [ CMSG_BLKIF_BE ]
-
-        self.subTypes = {
-            CMSG_BLKIF_BE_CREATE     : self.recv_be_create,
-            CMSG_BLKIF_BE_CONNECT    : self.recv_be_connect,
-            CMSG_BLKIF_BE_VBD_CREATE : self.recv_be_vbd_create,
-            CMSG_BLKIF_BE_VBD_GROW   : self.recv_be_vbd_grow,
-            CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
-            }
-        self.attached = 1
-        self.registerChannel()
-
-    def createInstance(self, dom, recreate=0):
-        d = self.addDeferred()
-        blkif = self.getInstanceByDom(dom)
-        if blkif:
-            self.callDeferred(blkif)
-        else:
-            blkif = BlkifController(self, dom)
-            self.addInstance(blkif)
-            if recreate:
-                self.callDeferred(blkif)
-            else:
-                blkif.send_be_create()
-        return d
-
-    def getDomainDevices(self, dom):
-        blkif = self.getInstanceByDom(dom)
-        return (blkif and blkif.getDevices()) or []
-
-    def getDomainDevice(self, dom, vdev):
-        blkif = self.getInstanceByDom(dom)
-        return (blkif and blkif.getDevice(vdev)) or None
-
-    def setControlDomain(self, dom, recreate=0):
-        if self.dom == dom: return
-        self.deregisterChannel()
-        if not recreate:
-            self.attached = 0
-        self.dom = dom
-        self.registerChannel()
-        #
-        #if xend.blkif.be_port:
-        #    xend.blkif.recovery = True
-        #xend.blkif.be_port = xend.main.port_from_dom(dom)
-
-    def getControlDomain(self):
-        return self.dom
-
-    def reattachDevice(self, dom, vdev):
-        blkif = self.getInstanceByDom(dom)
-        if blkif:
-            blkif.reattachDevice(vdev)
-        self.attached = self.devicesAttached()
-        if self.attached:
-            self.reattached()
-
-    def devicesAttached(self):
-        """Check if all devices are attached.
-        """
-        attached = 1
-        for blkif in self.getInstances():
-            if not blkif.attached:
-                attached = 0
-                break
-        return attached
-                         
-    def reattached(self):
-        for blkif in self.getInstances():
-            blkif.reattached()
-
-    def recv_be_create(self, msg, req):
-        #print 'recv_be_create>'
-        val = unpackMsg('blkif_be_create_t', msg)
-        blkif = self.getInstanceByDom(val['domid'])
-        self.callDeferred(blkif)
-    
-    def recv_be_connect(self, msg, req):
-        #print 'recv_be_create>'
-        val = unpackMsg('blkif_be_connect_t', msg)
-        blkif = self.getInstanceByDom(val['domid'])
-        if blkif:
-            blkif.send_fe_interface_status_changed()
-        else:
-            pass
-    
-    def recv_be_vbd_create(self, msg, req):
-        #print 'recv_be_vbd_create>'
-        val = unpackMsg('blkif_be_vbd_create_t', msg)
-        blkif = self.getInstanceByDom(val['domid'])
-        if blkif:
-            blkif.send_be_vbd_grow(val['vdevice'])
-        else:
-            pass
-    
-    def recv_be_vbd_grow(self, msg, req):
-        #print 'recv_be_vbd_grow>'
-        val = unpackMsg('blkif_be_vbd_grow_t', msg)
-        # Check status?
-        if self.attached:
-            self.callDeferred(0)
-        else:
-            self.reattachDevice(val['domid'], val['vdevice'])
-
-    def recv_be_driver_status_changed(self, msg, req):
-        val = unpackMsg('blkif_be_driver_status_changed_t', msg)
-        status = val['status']
-        if status == BLKIF_DRIVER_STATUS_UP and not self.attached:
-            for blkif in self.getInstances():
-                blkif.detach()
-
-class BlkDev(controller.Dev):
-    """Info record for a block device.
-    """
-
-    def __init__(self, ctrl, vdev, mode, segment):
-        controller.Dev.__init__(self, ctrl)
-        self.vdev = vdev
-        self.mode = mode
-        self.device = segment['device']
-        self.start_sector = segment['start_sector']
-        self.nr_sectors = segment['nr_sectors']
-        self.attached = 1
-
-    def readonly(self):
-        return 'w' not in self.mode
-
-    def sxpr(self):
-        val = ['blkdev', ['vdev', self.vdev], ['mode', self.mode] ]
-        return val
-
-    def destroy(self):
-        print 'BlkDev>destroy>', self.vdev
-        PrettyPrint.prettyprint(self.sxpr())
-        self.controller.send_be_vbd_destroy(self.vdev)
-        
-class BlkifController(controller.Controller):
-    """Block device interface controller. Handles all block devices
-    for a domain.
-    """
-    
-    def __init__(self, factory, dom):
-        #print 'BlkifController> dom=', dom
-        controller.Controller.__init__(self, factory, dom)
-        self.devices = {}
-
-        self.majorTypes = [ CMSG_BLKIF_FE ]
-
-        self.subTypes = {
-            CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
-                self.recv_fe_driver_status_changed,
-            CMSG_BLKIF_FE_INTERFACE_CONNECT    :
-                self.recv_fe_interface_connect,
-            }
-        self.attached = 1
-        self.evtchn = None
-        self.registerChannel()
-        #print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx
-
-    def sxpr(self):
-        val = ['blkif', ['dom', self.dom]]
-        if self.evtchn:
-            val.append(['evtchn',
-                        self.evtchn['port1'],
-                        self.evtchn['port2']])
-        return val
-
-    def lostChannel(self):
-        print 'BlkifController>lostChannel>', 'dom=', self.dom
-        #self.destroyDevices()
-        controller.Controller.lostChannel(self)
-
-    def getDevices(self):
-        return self.devices.values()
-
-    def getDevice(self, vdev):
-        return self.devices.get(vdev)
-
-    def addDevice(self, vdev, mode, segment):
-        if vdev in self.devices: return None
-        dev = BlkDev(self, vdev, mode, segment)
-        self.devices[vdev] = dev
-        return dev
-
-    def attachDevice(self, vdev, mode, segment, recreate=0):
-        """Attach a device to the specified interface.
-        """
-        #print 'BlkifController>attach_device>', self.dom, vdev, mode, segment
-        dev = self.addDevice(vdev, mode, segment)
-        if not dev: return -1
-        if recreate:
-            d = defer.Deferred()
-            d.callback(self)
-        else:
-            self.send_be_vbd_create(vdev)
-            d = self.factory.addDeferred()
-        return d
-
-    def destroy(self):
-        print 'BlkifController>destroy> dom=', self.dom
-        def cb_destroy(val):
-            self.send_be_destroy()
-        d = self.factory.addDeferred()
-        d.addCallback(cb_destroy)
-        self.send_be_disconnect()
-        #self.destroyDevices()
-
-    def destroyDevices(self):
-        for dev in self.getDevices():
-            dev.destroy()
-
-    def detach(self):
-        """Detach all devices, when the back-end control domain has changed.
-        """
-        self.attached = 0
-        for dev in self.devices.values():
-            dev.attached = 0
-            self.send_be_vbd_create(vdev)
-
-    def reattachDevice(self, vdev):
-        """Reattach a device, when the back-end control domain has changed.
-        """
-        dev = self.devices[vdev]
-        dev.attached = 1
-        attached = 1
-        for dev in self.devices.values():
-            if not dev.attached:
-                attached = 0
-                break
-        self.attached = attached
-        return self.attached
-
-    def reattached(self):
-        """All devices have been reattached after the back-end control
-        domain has changed.
-        """
-        msg = packMsg('blkif_fe_interface_status_changed_t',
-                      { 'handle' : 0,
-                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED})
-        self.writeRequest(msg)
-
-    def recv_fe_driver_status_changed(self, msg, req):
-        msg = packMsg('blkif_fe_interface_status_changed_t',
-                      { 'handle' : 0,
-                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED,
-                        'evtchn' : 0 })
-        self.writeRequest(msg)
-    
-    def recv_fe_interface_connect(self, msg, req):
-        val = unpackMsg('blkif_fe_interface_connect_t', msg)
-        self.evtchn = channel.eventChannel(0, self.dom)
-        print 'recv_fe_interface_connect>'
-        PrettyPrint.prettyprint(self.sxpr())
-        msg = packMsg('blkif_be_connect_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : val['handle'],
-                        'evtchn'       : self.evtchn['port1'],
-                        'shmem_frame'  : val['shmem_frame'] })
-        self.factory.writeRequest(msg)
-        pass
-
-    #def recv_fe_interface_status_changed(self, msg, req):
-    #    (hnd, status, chan) = unpackMsg('blkif_fe_interface_status_changed_t', msg)
-    #    print 'recv_fe_interface_status_changed>', hnd, status, chan
-    #   pass
-
-    def send_fe_interface_status_changed(self):
-        msg = packMsg('blkif_fe_interface_status_changed_t',
-                      { 'handle' : 0,
-                        'status' : BLKIF_INTERFACE_STATUS_CONNECTED,
-                        'evtchn' : self.evtchn['port2'] })
-        self.writeRequest(msg)
-
-    def send_be_create(self):
-        msg = packMsg('blkif_be_create_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : 0 })
-        self.factory.writeRequest(msg)
-
-    def send_be_disconnect(self):
-        print '>BlkifController>send_be_disconnect>', 'dom=', self.dom
-        msg = packMsg('blkif_be_disconnect_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : 0 })
-        self.factory.writeRequest(msg)
-
-    def send_be_destroy(self):
-        print '>BlkifController>send_be_destroy>', 'dom=', self.dom
-        msg = packMsg('blkif_be_destroy_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : 0 })
-        self.factory.writeRequest(msg)
-
-    def send_be_vbd_create(self, vdev):
-        dev = self.devices[vdev]
-        msg = packMsg('blkif_be_vbd_create_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : 0,
-                        'vdevice'      : dev.vdev,
-                        'readonly'     : dev.readonly() })
-        self.factory.writeRequest(msg)
-        
-    def send_be_vbd_grow(self, vdev):
-        dev = self.devices[vdev]
-        msg = packMsg('blkif_be_vbd_grow_t',
-                      { 'domid'                : self.dom,
-                        'blkif_handle'         : 0,
-                        'vdevice'              : dev.vdev,
-                        'extent.device'        : dev.device,
-                        'extent.sector_start'  : dev.start_sector,
-                        'extent.sector_length' : dev.nr_sectors })
-        self.factory.writeRequest(msg)
-
-    def send_be_vbd_destroy(self, vdev):
-        print '>BlkifController>send_be_vbd_destroy>', 'dom=', self.dom, 'vdev=', vdev
-        PrettyPrint.prettyprint(self.sxpr())
-        dev = self.devices[vdev]
-        msg = packMsg('blkif_be_vbd_destroy_t',
-                      { 'domid'                : self.dom,
-                        'blkif_handle'         : 0,
-                        'vdevice'              : dev.vdev })
-        del self.devices[vdev]
-        self.factory.writeRequest(msg)
-    
diff --git a/tools/xen/lib/xend/server/channel.py b/tools/xen/lib/xend/server/channel.py
deleted file mode 100755 (executable)
index be98a37..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-import xen.ext.xc; xc = xen.ext.xc.new()
-from xen.ext import xu
-from messages import msgTypeName
-
-VIRQ_MISDIRECT  = 0  # Catch-all interrupt for unbound VIRQs.
-VIRQ_TIMER      = 1  # Timebase update, and/or requested timeout.
-VIRQ_DEBUG      = 2  # Request guest to dump debug info.
-VIRQ_CONSOLE    = 3  # (DOM0) bytes received on emergency console.
-VIRQ_DOM_EXC    = 4  # (DOM0) Exceptional event for some domain.
-
-def eventChannel(dom1, dom2):
-    return xc.evtchn_bind_interdomain(dom1=dom1, dom2=dom2)
-
-class ChannelFactory:
-    """Factory for creating channels.
-    Maintains a table of channels.
-    """
-
-    """ Channels indexed by index. """
-    channels = {}
-
-    def __init__(self):
-        """Constructor - do not use. Use the channelFactory function."""
-        self.notifier = xu.notifier()
-    
-    def addChannel(self, channel):
-        """Add a channel.
-        """
-        idx = channel.idx
-        self.channels[idx] = channel
-        self.notifier.bind(idx)
-        # Try to wake it up
-        #self.notifier.unmask(idx)
-        #channel.notify()
-
-    def getChannel(self, idx):
-        """Get the channel with the given index (if any).
-        """
-        return self.channels.get(idx)
-
-    def delChannel(self, idx):
-        """Remove the channel with the given index (if any).
-        """
-        if idx in self.channels:
-            del self.channels[idx]
-            self.notifier.unbind(idx)
-
-    def domChannel(self, dom):
-        """Get the channel for the given domain.
-        Construct if necessary.
-        """
-        dom = int(dom)
-        for chan in self.channels.values():
-            if not isinstance(chan, Channel): continue
-            if chan.dom == dom:
-                return chan
-        chan = Channel(self, dom)
-        self.addChannel(chan)
-        return chan
-
-    def virqChannel(self, virq):
-        """Get the channel for the given virq.
-        Construct if necessary.
-        """
-        for chan in self.channels.values():
-            if not isinstance(chan, VirqChannel): continue
-            if chan.virq == virq:
-                return chan
-        chan = VirqChannel(self, virq)
-        self.addChannel(chan)
-        return chan
-
-    def channelClosed(self, channel):
-        """The given channel has been closed - remove it.
-        """
-        self.delChannel(channel.idx)
-
-    def createPort(self, dom):
-        """Create a port for a channel to the given domain.
-        """
-        return xu.port(dom)
-
-def channelFactory():
-    """Singleton constructor for the channel factory.
-    Use this instead of the class constructor.
-    """
-    global inst
-    try:
-        inst
-    except:
-        inst = ChannelFactory()
-    return inst
-
-class BaseChannel:
-    """Abstract superclass for channels.
-
-    The subclass constructor must set idx to the port to use.
-    """
-
-    def __init__(self, factory):
-        self.factory = factory
-        self.idx = -1
-        self.closed = 0
-
-    def getIndex(self):
-        """Get the channel index.
-        """
-        return self.idx
-
-    def notificationReceived(self, type):
-        """Called when a notification is received.
-        Closes the channel on error, otherwise calls
-        handleNotification(type), which should be defined
-        in a subclass.
-        """
-        #print 'notificationReceived> type=', type, self
-        if self.closed: return
-        if type == self.factory.notifier.EXCEPTION:
-            print 'notificationReceived> EXCEPTION'
-            info = xc.evtchn_status(self.idx)
-            if info['status'] == 'unbound':
-                print 'notificationReceived> EXCEPTION closing...'
-                self.close()
-                return
-        self.handleNotification(type)
-
-    def close(self):
-        """Close the channel. Calls channelClosed() on the factory.
-        Override in subclass.
-        """
-        self.factory.channelClosed(self)
-
-    def handleNotification(self, type):
-        """Handle notification.
-        Define in subclass.
-        """
-        pass
-        
-
-class VirqChannel(BaseChannel):
-    """A channel for handling a virq.
-    """
-    
-    def __init__(self, factory, virq):
-        """Create a channel for the given virq using the given factory.
-
-        Do not call directly, use virqChannel on the factory.
-        """
-        BaseChannel.__init__(self, factory)
-        self.virq = virq
-        # Notification port (int).
-        self.port = xc.evtchn_bind_virq(virq)
-        self.idx = self.port
-        # Clients to call when a virq arrives.
-        self.clients = []
-
-    def __repr__(self):
-        return ('<VirqChannel virq=%d port=%d>'
-                % (self.virq, self.port))
-
-    def getVirq(self):
-        """Get the channel's virq.
-        """
-        return self.virq
-
-    def close(self):
-        """Close the channel. Calls lostChannel(self) on all its clients and
-        channelClosed() on the factory.
-        """
-        for c in self.clients:
-            c.lostChannel(self)
-        del self.clients
-        BaseChannel.close(self)
-
-    def registerClient(self, client):
-        """Register a client. The client will be called with
-        client.virqReceived(virq) when a virq is received.
-        The client will be called with client.lostChannel(self) if the
-        channel is closed.
-        """
-        self.clients.append(client)
-
-    def handleNotification(self, type):
-        for c in self.clients:
-            c.virqReceived(self.virq)
-
-    def notify(self):
-        xc.evtchn_send(self.port)
-
-
-class Channel(BaseChannel):
-    """A control channel to a domain. Messages for the domain device controllers
-    are multiplexed over the channel (console, block devs, net devs).
-    """
-
-    def __init__(self, factory, dom):
-        """Create a channel to the given domain using the given factory.
-
-        Do not call directly, use domChannel on the factory.
-        """
-        BaseChannel.__init__(self, factory)
-        # Domain.
-        self.dom = int(dom)
-        # Domain port (object).
-        self.port = self.factory.createPort(dom)
-        # Channel port (int).
-        self.idx = self.port.local_port
-        # Registered devices.
-        self.devs = []
-        # Devices indexed by the message types they handle.
-        self.devs_by_type = {}
-        # Output queue.
-        self.queue = []
-        self.closed = 0
-
-    def getLocalPort(self):
-        """Get the local port.
-        """
-        return self.port.local_port
-
-    def getRemotePort(self):
-        """Get the remote port.
-        """
-        return self.port.remote_port
-
-    def close(self):
-        """Close the channel. Calls lostChannel() on all its devices and
-        channelClosed() on the factory.
-        """
-        self.closed = 1
-        for d in self.devs:
-            d.lostChannel()
-        self.factory.channelClosed(self)
-        self.devs = []
-        self.devs_by_type = {}
-
-    def registerDevice(self, types, dev):
-        """Register a device controller.
-
-        @param types message types the controller handles
-        @param dev   device controller
-        """
-        if self.closed: return
-        self.devs.append(dev)
-        for ty in types:
-            self.devs_by_type[ty] = dev
-
-    def deregisterDevice(self, dev):
-        """Remove the registration for a device controller.
-
-        @param dev device controller
-        """
-        if dev in self.devs:
-            self.devs.remove(dev)
-        types = [ ty for (ty, d) in self.devs_by_type.items() if d == dev ]
-        for ty in types:
-            del self.devs_by_type[ty]
-
-    def getDevice(self, type):
-        """Get the device controller handling a message type.
-
-        @param type message type
-        @returns controller or None
-        """
-        return self.devs_by_type.get(type)
-
-    def getMessageType(self, msg):
-        """Get a 2-tuple of the message type and subtype.
-        """
-        hdr = msg.get_header()
-        return (hdr['type'], hdr.get('subtype'))
-
-    def __repr__(self):
-        return ('<Channel dom=%d ports=%d:%d>'
-                % (self.dom,
-                   self.port.local_port,
-                   self.port.remote_port))
-
-    def handleNotification(self, type):
-        work = 0
-        work += self.handleRequests()
-        work += self.handleResponses()
-        work += self.handleWrites()
-        if work:
-            self.notify()
-
-    def notify(self):
-        self.port.notify()
-
-    def handleRequests(self):
-        work = 0
-        while 1:
-            msg = self.readRequest()
-            if not msg: break
-            self.requestReceived(msg)
-            work += 1
-        return work
-
-    def requestReceived(self, msg):
-        (ty, subty) = self.getMessageType(msg)
-        #todo:  Must respond before writing any more messages.
-        #todo:  Should automate this (respond on write)
-        self.port.write_response(msg)
-        dev = self.getDevice(ty)
-        if dev:
-            dev.requestReceived(msg, ty, subty)
-        else:
-            print ("requestReceived> No device: Message type %s %d:%d"
-                   % (msgTypeName(ty, subty), ty, subty)), self
-
-    def handleResponses(self):
-        work = 0
-        while 1:
-            msg = self.readResponse()
-            if not msg: break
-            self.responseReceived(msg)
-            work += 1
-        return work
-
-    def responseReceived(self, msg):
-        (ty, subty) = self.getMessageType(msg)
-        dev = self.getDevice(ty)
-        if dev:
-            dev.responseReceived(msg, ty, subty)
-        else:
-            print ("responseReceived> No device: Message type %d:%d"
-                   % (msgTypeName(ty, subty), ty, subty)), self
-
-    def handleWrites(self):
-        work = 0
-        # Pull data from producers.
-        for dev in self.devs:
-            work += dev.produceRequests()
-        # Flush the queue.
-        while self.queue and self.port.space_to_write_request():
-            msg = self.queue.pop(0)
-            self.port.write_request(msg)
-            work += 1
-        return work
-
-    def writeRequest(self, msg, notify=1):
-        if self.closed:
-            val = -1
-        elif self.writeReady():
-            self.port.write_request(msg)
-            if notify: self.notify()
-            val = 1
-        else:
-            self.queue.append(msg)
-            val = 0
-        return val
-
-    def writeResponse(self, msg):
-        if self.closed: return -1
-        self.port.write_response(msg)
-        return 1
-
-    def writeReady(self):
-        if self.closed or self.queue: return 0
-        return self.port.space_to_write_request()
-
-    def readRequest(self):
-        if self.closed:
-            return None
-        if self.port.request_to_read():
-            val = self.port.read_request()
-        else:
-            val = None
-        return val
-        
-    def readResponse(self):
-        if self.closed:
-            return None
-        if self.port.response_to_read():
-            val = self.port.read_response()
-        else:
-            val = None
-        return val
diff --git a/tools/xen/lib/xend/server/console.py b/tools/xen/lib/xend/server/console.py
deleted file mode 100755 (executable)
index ab8b22e..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-
-from twisted.internet import reactor
-from twisted.internet import protocol
-from twisted.protocols import telnet
-
-from xen.ext import xu
-
-from xen.xend import EventServer
-eserver = EventServer.instance()
-
-import controller
-from messages import *
-from params import *
-
-"""Telnet binary option."""
-TRANSMIT_BINARY = '0'
-WILL = chr(251)
-IAC = chr(255)
-
-class ConsoleProtocol(protocol.Protocol):
-    """Asynchronous handler for a console TCP socket.
-    """
-
-    def __init__(self, controller, idx):
-        self.controller = controller
-        self.idx = idx
-        self.addr = None
-        self.binary = 0
-
-    def connectionMade(self):
-        peer = self.transport.getPeer()
-        self.addr = (peer.host, peer.port)
-        if self.controller.connect(self.addr, self):
-            self.transport.write("Cannot connect to console %d on domain %d\n"
-                                 % (self.idx, self.controller.dom))
-            self.loseConnection()
-            return
-        else:
-            # KAF: A nice quiet successful connect. Don't bother with telnet
-            # control sequence -- telnet is not the appropriate protocol here. 
-            #self.transport.write("Connected to console %d on domain %d\n"
-            #                     % (self.idx, self.controller.dom))
-            #self.setTelnetTransmitBinary()
-            eserver.inject('xend.console.connect',
-                           [self.idx, self.addr[0], self.addr[1]])
-
-    def setTelnetTransmitBinary(self):
-        """Send the sequence to set the telnet TRANSMIT-BINARY option.
-        """
-        self.write(IAC + WILL + TRANSMIT_BINARY)
-
-    def dataReceived(self, data):
-        if self.controller.handleInput(self, data):
-            self.loseConnection()
-
-    def write(self, data):
-        #if not self.connected: return -1
-        self.transport.write(data)
-        return len(data)
-
-    def connectionLost(self, reason=None):
-        eserver.inject('xend.console.disconnect',
-                       [self.idx, self.addr[0], self.addr[1]])
-        self.controller.disconnect()
-
-    def loseConnection(self):
-        self.transport.loseConnection()
-
-class ConsoleFactory(protocol.ServerFactory):
-    """Asynchronous handler for a console server socket.
-    """
-    protocol = ConsoleProtocol
-    
-    def __init__(self, controller, idx):
-        #protocol.ServerFactory.__init__(self)
-        self.controller = controller
-        self.idx = idx
-
-    def buildProtocol(self, addr):
-        proto = self.protocol(self.controller, self.idx)
-        proto.factory = self
-        return proto
-
-class ConsoleControllerFactory(controller.ControllerFactory):
-    """Factory for creating console controllers.
-    """
-
-    def createInstance(self, dom, console_port=None):
-        if console_port is None:
-            console_port = CONSOLE_PORT_BASE + dom
-        console = ConsoleController(self, dom, console_port)
-        self.addInstance(console)
-        eserver.inject('xend.console.create',
-                       [console.idx, console.dom, console.console_port])
-        return console
-        
-    def consoleClosed(self, console):
-        eserver.inject('xend.console.close', console.idx)
-        self.delInstance(console)
-
-class ConsoleController(controller.Controller):
-    """Console controller for a domain.
-    Does not poll for i/o itself, but relies on the notifier to post console
-    output and the connected TCP sockets to post console input.
-    """
-
-    def __init__(self, factory, dom, console_port):
-        #print 'ConsoleController> dom=', dom, type(dom)
-        controller.Controller.__init__(self, factory, dom)
-        self.majorTypes = [ CMSG_CONSOLE ]
-        self.status = "new"
-        self.addr = None
-        self.conn = None
-        self.rbuf = xu.buffer()
-        self.wbuf = xu.buffer()
-        self.console_port = console_port
-
-        self.registerChannel()
-        self.listener = None
-        self.listen()
-        #print 'ConsoleController<', 'dom=', self.dom, 'idx=', self.idx
-
-    def sxpr(self):
-        val =['console',
-              ['status',       self.status ],
-              ['id',           self.idx ],
-              ['domain',       self.dom ],
-              ['local_port',   self.channel.getLocalPort() ],
-              ['remote_port',  self.channel.getRemotePort() ],
-              ['console_port', self.console_port ] ]
-        if self.addr:
-            val.append(['connected', self.addr[0], self.addr[1]])
-        return val
-
-    def ready(self):
-        return not (self.closed() or self.rbuf.empty())
-
-    def closed(self):
-        return self.status == 'closed'
-
-    def connected(self):
-        return self.status == 'connected'
-
-    def close(self):
-        try:
-            #print 'ConsoleController> close dom=', self.dom
-            self.status = "closed"
-            if self.conn:
-                self.conn.loseConnection()
-            self.listener.stopListening()
-            self.deregisterChannel()
-            self.lostChannel()
-        except Exception, ex:
-            print 'ConsoleController>close>', ex
-            raise
-
-    def listen(self):
-        """Listen for TCP connections to the console port..
-        """
-        if self.closed(): return
-        self.status = "listening"
-        if self.listener:
-            #self.listener.startListening()
-            pass
-        else:
-            f = ConsoleFactory(self, self.idx)
-            self.listener = reactor.listenTCP(self.console_port, f)
-
-    def connect(self, addr, conn):
-        if self.closed(): return -1
-        if self.connected(): return -1
-        self.addr = addr
-        self.conn = conn
-        self.status = "connected"
-        self.handleOutput()
-        return 0
-
-    def disconnect(self):
-        if self.conn:
-            self.conn.loseConnection()
-        self.addr = None
-        self.conn = None
-        self.listen()
-
-    def requestReceived(self, msg, type, subtype):
-        #print '***Console', self.dom, msg.get_payload()
-        self.rbuf.write(msg.get_payload())
-        self.handleOutput()
-        
-    def responseReceived(self, msg, type, subtype):
-        pass
-
-    def produceRequests(self):
-        # Send as much pending console data as there is room for.
-        work = 0
-        while not self.wbuf.empty() and self.channel.writeReady():
-            msg = xu.message(CMSG_CONSOLE, 0, 0)
-            msg.append_payload(self.wbuf.read(msg.MAX_PAYLOAD))
-            work += self.channel.writeRequest(msg, notify=0)
-        return work
-
-    def handleInput(self, conn, data):
-        """Handle some external input aimed at the console.
-        Called from a TCP connection (conn).
-        """
-        if self.closed(): return -1
-        if conn != self.conn: return 0
-        self.wbuf.write(data)
-        if self.produceRequests():
-            self.channel.notify()
-        return 0
-
-    def handleOutput(self):
-        """Handle buffered output from the console.
-        Sends it to the connected console (if any).
-        """
-        if self.closed():
-            #print 'Console>handleOutput> closed'
-            return -1
-        if not self.conn:
-            #print 'Console>handleOutput> not connected'
-            return 0
-        while not self.rbuf.empty():
-            try:
-                #print 'Console>handleOutput> writing...'
-                bytes = self.conn.write(self.rbuf.peek())
-                if bytes > 0:
-                    self.rbuf.discard(bytes)
-            except socket.error, error:
-                pass
-        #print 'Console>handleOutput<'
-        return 0
diff --git a/tools/xen/lib/xend/server/controller.py b/tools/xen/lib/xend/server/controller.py
deleted file mode 100755 (executable)
index 900c2d5..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-from twisted.internet import defer
-
-import channel
-from messages import msgTypeName
-
-class CtrlMsgRcvr:
-    """Abstract class for things that deal with a control interface to a domain.
-    """
-
-
-    def __init__(self):
-        self.channelFactory = channel.channelFactory()
-        self.majorTypes = [ ]
-        self.subTypes = {}
-        self.dom = None
-        self.channel = None
-        self.idx = None
-
-    def requestReceived(self, msg, type, subtype):
-        method = self.subTypes.get(subtype)
-        if method:
-            method(msg, 1)
-        else:
-            print ('requestReceived> No handler: Message type %s %d:%d'
-                   % (msgTypeName(type, subtype), type, subtype)), self
-        
-    def responseReceived(self, msg, type, subtype):
-        method = self.subTypes.get(subtype)
-        if method:
-            method(msg, 0)
-        else:
-            print ('responseReceived> No handler: Message type %s %d:%d'
-                   % (msgTypeName(type, subtype), type, subtype)), self
-
-    def lostChannel(self):
-        pass
-    
-    def registerChannel(self):
-        #print 'CtrlMsgRcvr>registerChannel>', self
-        self.channel = self.channelFactory.domChannel(self.dom)
-        self.idx = self.channel.getIndex()
-        if self.majorTypes:
-            self.channel.registerDevice(self.majorTypes, self)
-        
-    def deregisterChannel(self):
-        #print 'CtrlMsgRcvr>deregisterChannel>', self
-        if self.channel:
-            self.channel.deregisterDevice(self)
-            del self.channel
-
-    def produceRequests(self):
-        return 0
-
-    def writeRequest(self, msg):
-        if self.channel:
-            self.channel.writeRequest(msg)
-        else:
-            print 'CtrlMsgRcvr>writeRequest>', 'no channel!', self
-
-    def writeResponse(self, msg):
-        if self.channel:
-            self.channel.writeResponse(msg)
-        else:
-            print 'CtrlMsgRcvr>writeResponse>', 'no channel!', self
-            
-class ControllerFactory(CtrlMsgRcvr):
-    """Abstract class for factories creating controllers.
-    Maintains a table of instances.
-    """
-
-    def __init__(self):
-        CtrlMsgRcvr.__init__(self)
-        self.instances = {}
-        self.dlist = []
-        self.dom = 0
-        # Timeout (in seconds) for deferreds.
-        self.timeout = 10
-        
-    def addInstance(self, instance):
-        self.instances[instance.idx] = instance
-
-    def getInstance(self, idx):
-        return self.instances.get(idx)
-
-    def getInstances(self):
-        return self.instances.values()
-
-    def getInstanceByDom(self, dom):
-        for inst in self.instances.values():
-            if inst.dom == dom:
-                return inst
-        return None
-
-    def delInstance(self, instance):
-        #print 'ControllerFactory>delInstance>', instance.idx
-        if instance.idx in self.instances:
-            #print 'ControllerFactory>delInstance> remove', instance.idx
-            del self.instances[instance.idx]
-
-    def createInstance(self, dom, recreate=0):
-        raise NotImplementedError()
-
-    def instanceClosed(self, instance):
-        #print 'ControllerFactory>instanceClosed>', instance.idx, instance
-        self.delInstance(instance)
-
-    def addDeferred(self):
-        d = defer.Deferred()
-        if self.timeout > 0:
-            # The deferred will error if not called before timeout.
-            d.setTimeout(self.timeout)
-        self.dlist.append(d)
-        return d
-
-    def callDeferred(self, *args):
-        if self.dlist:
-            d = self.dlist.pop(0)
-            d.callback(*args)
-
-    def errDeferred(self, *args):
-        if self.dlist:
-            d = self.dlist.pop(0)
-            d.errback(*args)
-
-class Controller(CtrlMsgRcvr):
-    """Abstract class for a device controller attached to a domain.
-    """
-
-    def __init__(self, factory, dom):
-        CtrlMsgRcvr.__init__(self)
-        self.factory = factory
-        self.dom = int(dom)
-        self.channel = None
-        self.idx = None
-
-    def close(self):
-        self.deregisterChannel()
-        self.lostChannel()
-
-    def lostChannel(self):
-        #print 'Controller>lostChannel>', self, self.factory
-        self.factory.instanceClosed(self)
-
-class Dev:
-
-    def __init__(self, controller):
-        self.controller = controller
-        self.props = {}
-
-    def setprop(self, k, v):
-        self.props[k] = v
-
-    def getprop(self, k, v=None):
-        return self.props.get(k, v)
-
-    def hasprop(self, k):
-        return k in self.props
-
-    def delprop(self, k):
-        if k in self.props:
-            del self.props[k]
-
-    #def __repr__(self):
-    #    return str(self.sxpr())
-
-    def sxpr(self):
-        raise NotImplementedError()
-
-    
diff --git a/tools/xen/lib/xend/server/cstruct.py b/tools/xen/lib/xend/server/cstruct.py
deleted file mode 100755 (executable)
index 880931b..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-import struct
-
-class Struct:
-
-    maxDepth = 10
-
-    base = ['x', 'B', 'H', 'I', 'L', 'Q', 'c', 'h', 'i', 'l', 'q', ]
-
-    sizes = {'B': 1,
-            'H': 2,
-            'I': 4,
-            'L': 4,
-            'Q': 8,
-            'c': 1,
-            'h': 2,
-            'i': 4,
-            'l': 4,
-            'q': 8,
-            'x': 1,
-            }
-
-    formats = {
-        'int8'          : 'B',
-        'int16'         : 'H',
-        'int32'         : 'I',
-        'int64'         : 'Q',
-        'u8'            : 'B',
-        'u16'           : 'H',
-        'u32'           : 'I',
-        'u64'           : 'Q'
-        }
-
-    def typedef(self, name, val):
-        self.formats[name] = val
-
-    def struct(self, name, *f):
-        self.typedef(name, StructInfo(self, f))
-        
-    def getType(self, name):
-        return self.formats[name]
-
-    def format(self, ty):
-        d = 0
-        f = ty
-        while d < self.maxDepth:
-            d += 1
-            f = self.formats[f]
-            if isinstance(f, StructInfo):
-                return f.format()
-            if f in self.base:
-                return f
-        return -1
-
-    def alignedformat(self, ty):
-        fmt = self.format(ty)
-        #print 'alignedformat> %s |%s|' %(ty, fmt)
-        afmt = self.align(fmt)
-        #print 'alignedformat< %s |%s| |%s|' % (ty, fmt, afmt)
-        return afmt
-
-    def align(self, fmt):
-        n1 = 0
-        afmt = ''
-        for a in fmt:
-            n2 = self.getSize(a)
-            m = n1 % n2
-            if m:
-                d = (n2 - m)
-                afmt += 'x' * d
-                n1 += d
-            afmt += a
-            n1 += n2
-        return afmt
-
-    def fmtsize(self, fmt):
-        s = 0
-        for f in fmt:
-            s += self.getSize(f)
-        return s
-
-    def getSize(self, f):
-        return self.sizes[f]
-
-    def pack(self, ty, data):
-        return self.getType(ty).pack(data)
-
-    def unpack(self, ty, data):
-        return self.getType(ty).unpack(data)
-
-    def show(self):
-        l = self.formats.keys()
-        l.sort()
-        for v in l:
-            print "%-35s %-10s %s" % (v, self.format(v), self.alignedformat(v))
-
-
-class StructInfo:
-
-    def __init__(self, s, f):
-        self.fmt = None
-        self.structs = s
-        self.fields = f
-
-    def alignedformat(self):
-        if self.afmt: return self.afmt
-        self.afmt = self.structs.align(self.format())
-        return self.afmt
-    
-    def format(self):
-        if self.fmt: return self.fmt
-        fmt = ""
-        for (ty, name) in self.fields:
-            fmt += self.formatString(ty)
-        self.fmt = fmt
-        return fmt
-
-    def formatString(self, ty):
-        if ty in self.fields:
-            ty = self.fields[ty]
-        return self.structs.format(ty)
-
-    def pack(self, *args):
-        return struct.pack(self.alignedformat(), *args)
-
-    def unpack(self, data):
-        return struct.unpack(self.alignedformat(), data)
-
-types = Struct()
-
-types.typedef('short'         , 'h')
-types.typedef('int'           , 'i')
-types.typedef('long'          , 'l')
-types.typedef('unsigned short', 'H')
-types.typedef('unsigned int'  , 'I')
-types.typedef('unsigned long' , 'L')
-types.typedef('domid_t'       , 'u64')
-types.typedef('blkif_vdev_t'  , 'u16')
-types.typedef('blkif_pdev_t'  , 'u16')
-types.typedef('blkif_sector_t', 'u64')
-
-types.struct('u8[6]',
-             ('u8', 'a1'),
-             ('u8', 'a2'),
-             ('u8', 'a3'),
-             ('u8', 'a4'),
-             ('u8', 'a5'),
-             ('u8', 'a6'))
-             
-types.struct('blkif_fe_interface_status_changed_t',
-    ('unsigned int',    'handle'),
-    ('unsigned int',    'status'),
-    ('unsigned int',    'evtchn'))
-
-types.struct('blkif_fe_driver_status_changed_t',
-    ('unsigned int',    'status'),
-    ('unsigned int',    'nr_interfaces'))
-
-types.struct('blkif_fe_interface_connect_t',
-    ('unsigned int' ,   'handle'),
-    ('unsigned long',   'shmem_frame'))
-
-types.struct('blkif_fe_interface_disconnect_t',
-    ('unsigned int',   'handle'))
-
-types.struct('blkif_extent_t',
-    ('blkif_pdev_t'  , 'device'),
-    ('blkif_sector_t', 'sector_start'),
-    ('blkif_sector_t', 'sector_length'))
-
-types.struct('blkif_be_create_t', 
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'blkif_handle'),
-    ('unsigned int',   'status'))
-             
-types.struct('blkif_be_destroy_t',
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'blkif_handle'),
-    ('unsigned int',   'status'))
-
-types.struct('blkif_be_connect_t',
-    ('domid_t'      ,  'domid'),
-    ('unsigned int' ,  'blkif_handle'),
-    ('unsigned int' ,  'evtchn'),
-    ('unsigned long',  'shmem_frame'),
-    ('unsigned int' ,  'status'))
-
-types.struct('blkif_be_disconnect_t',
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'blkif_handle'),
-    ('unsigned int',   'status'))
-
-types.struct('blkif_be_vbd_create_t', 
-    ('domid_t'     ,   'domid'),         #Q
-    ('unsigned int',   'blkif_handle'),  #I
-    ('blkif_vdev_t',   'vdevice'),       #H
-    ('int'         ,   'readonly'),      #i
-    ('unsigned int',   'status'))        #I
-
-types.struct('blkif_be_vbd_destroy_t', 
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'blkif_handle'),
-    ('blkif_vdev_t',   'vdevice'),
-    ('unsigned int',   'status'))
-
-types.struct('blkif_be_vbd_grow_t', 
-    ('domid_t'       , 'domid'),         #Q
-    ('unsigned int'  , 'blkif_handle'),  #I
-    ('blkif_vdev_t'  , 'vdevice'),       #H   
-    ('blkif_extent_t', 'extent'),        #HQQ
-    ('unsigned int'  , 'status'))        #I
-
-types.struct('blkif_be_vbd_shrink_t', 
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'blkif_handle'),
-    ('blkif_vdev_t',   'vdevice'),
-    ('unsigned int',   'status'))
-
-types.struct('blkif_be_driver_status_changed_t',
-    ('unsigned int',   'status'),
-    ('unsigned int',   'nr_interfaces'))
-
-types.struct('netif_fe_interface_status_changed_t',
-    ('unsigned int',   'handle'),
-    ('unsigned int',   'status'),
-    ('unsigned int',   'evtchn'),
-    ('u8[6]',          'mac'))
-
-types.struct('netif_fe_driver_status_changed_t',
-    ('unsigned int',   'status'),
-    ('unsigned int',   'nr_interfaces'))
-
-types.struct('netif_fe_interface_connect_t',
-    ('unsigned int',   'handle'),
-    ('unsigned long',  'tx_shmem_frame'),
-    ('unsigned long',  'rx_shmem_frame'))
-
-types.struct('netif_fe_interface_disconnect_t',
-    ('unsigned int',   'handle'))
-
-types.struct('netif_be_create_t', 
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'netif_handle'),
-    ('u8[6]'       ,   'mac'),
-    ('unsigned int',   'status'))
-
-types.struct('netif_be_destroy_t',
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'netif_handle'),
-    ('unsigned int',   'status'))
-
-types.struct('netif_be_connect_t', 
-    ('domid_t'      ,  'domid'),
-    ('unsigned int' ,  'netif_handle'),
-    ('unsigned int' ,  'evtchn'),
-    ('unsigned long',  'tx_shmem_frame'),
-    ('unsigned long',  'rx_shmem_frame'),
-    ('unsigned int' ,  'status'))
-
-types.struct('netif_be_disconnect_t',
-    ('domid_t'     ,   'domid'),
-    ('unsigned int',   'netif_handle'),
-    ('unsigned int',   'status'))
-
-types.struct('netif_be_driver_status_changed_t',
-    ('unsigned int',   'status'),
-    ('unsigned int',   'nr_interfaces'))
-
-if 1 or __name__ == "__main__":
-    types.show()
diff --git a/tools/xen/lib/xend/server/domain.py b/tools/xen/lib/xend/server/domain.py
deleted file mode 100644 (file)
index ab22234..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-import channel
-import controller
-from messages import *
-
-class DomainControllerFactory(controller.ControllerFactory):
-    """Factory for creating domain controllers.
-    """
-
-    def createInstance(self, dom):
-        d = DomainController(self, dom)
-        self.addInstance(d)
-        return d
-    
-    def getInstanceByDom(self, dom):
-        for inst in self.instances.values():
-            if inst.dom == dom:
-                return inst
-        inst = self.createInstance(dom)
-        return inst
-
-
-class DomainController(controller.Controller):
-    """Generic controller for a domain.
-    """
-
-    reasons = {'poweroff' : 'shutdown_poweroff_t',
-               'reboot'   : 'shutdown_reboot_t',
-               'suspend'  : 'shutdown_suspend_t' }
-
-    def __init__(self, factory, dom):
-        controller.Controller.__init__(self, factory, dom)
-        self.majorTypes = [ CMSG_SHUTDOWN ]
-        self.registerChannel()
-        print 'DomainController>', self, self.channel, self.idx
-
-    def shutdown(self, reason):
-        msgtype = self.reasons.get(reason)
-        if not msgtype:
-            raise ValueError('invalid reason:' + reason)
-        msg = packMsg(msgtype, {})
-        self.writeRequest(msg)
diff --git a/tools/xen/lib/xend/server/messages.py b/tools/xen/lib/xend/server/messages.py
deleted file mode 100644 (file)
index e12d7b6..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-import struct
-
-from xen.ext import xu
-
-DEBUG = 0
-
-""" All message formats.
-Added to incrementally for the various message types.
-See below.
-"""
-msg_formats = {}
-
-#============================================================================
-# Console message types.
-#============================================================================
-
-CMSG_CONSOLE  = 0
-
-console_formats = { 'console_data': (CMSG_CONSOLE, 0) }
-
-msg_formats.update(console_formats)
-
-#============================================================================
-# Block interface message types.
-#============================================================================
-
-CMSG_BLKIF_BE = 1
-CMSG_BLKIF_FE = 2
-
-CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED =  0
-CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED    = 32
-CMSG_BLKIF_FE_INTERFACE_CONNECT        = 33
-CMSG_BLKIF_FE_INTERFACE_DISCONNECT     = 34
-
-CMSG_BLKIF_BE_CREATE      = 0
-CMSG_BLKIF_BE_DESTROY     = 1
-CMSG_BLKIF_BE_CONNECT     = 2
-CMSG_BLKIF_BE_DISCONNECT  = 3
-CMSG_BLKIF_BE_VBD_CREATE  = 4
-CMSG_BLKIF_BE_VBD_DESTROY = 5
-CMSG_BLKIF_BE_VBD_GROW    = 6
-CMSG_BLKIF_BE_VBD_SHRINK  = 7
-CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED    = 32
-
-BLKIF_DRIVER_STATUS_DOWN  = 0
-BLKIF_DRIVER_STATUS_UP    = 1
-
-BLKIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
-BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
-BLKIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
-
-BLKIF_BE_STATUS_OKAY                = 0
-BLKIF_BE_STATUS_ERROR               = 1
-BLKIF_BE_STATUS_INTERFACE_EXISTS    = 2
-BLKIF_BE_STATUS_INTERFACE_NOT_FOUND = 3
-BLKIF_BE_STATUS_INTERFACE_CONNECTED = 4
-BLKIF_BE_STATUS_VBD_EXISTS          = 5
-BLKIF_BE_STATUS_VBD_NOT_FOUND       = 6
-BLKIF_BE_STATUS_OUT_OF_MEMORY       = 7
-BLKIF_BE_STATUS_EXTENT_NOT_FOUND    = 8
-BLKIF_BE_STATUS_MAPPING_ERROR       = 9
-
-blkif_formats = {
-    'blkif_be_connect_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT),
-
-    'blkif_be_create_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE),
-
-    'blkif_be_disconnect_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT),
-
-    'blkif_be_destroy_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY),
-
-    'blkif_be_vbd_create_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE),
-
-    'blkif_be_vbd_grow_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW),
-
-    'blkif_be_vbd_destroy_t':
-    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY),
-
-    'blkif_fe_interface_status_changed_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED),
-
-    'blkif_fe_driver_status_changed_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED),
-
-    'blkif_fe_interface_connect_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT),
-}
-
-msg_formats.update(blkif_formats)
-
-#============================================================================
-# Network interface message types.
-#============================================================================
-
-CMSG_NETIF_BE = 3
-CMSG_NETIF_FE = 4
-
-CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED =  0
-CMSG_NETIF_FE_DRIVER_STATUS_CHANGED    = 32
-CMSG_NETIF_FE_INTERFACE_CONNECT        = 33
-CMSG_NETIF_FE_INTERFACE_DISCONNECT     = 34
-
-CMSG_NETIF_BE_CREATE      = 0
-CMSG_NETIF_BE_DESTROY     = 1
-CMSG_NETIF_BE_CONNECT     = 2
-CMSG_NETIF_BE_DISCONNECT  = 3
-CMSG_NETIF_BE_DRIVER_STATUS_CHANGED    = 32
-
-NETIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
-NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
-NETIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
-
-NETIF_DRIVER_STATUS_DOWN   = 0
-NETIF_DRIVER_STATUS_UP     = 1
-
-netif_formats = {
-    'netif_be_connect_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT),
-
-    'netif_be_create_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE),
-
-    'netif_be_disconnect_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT),
-
-    'netif_be_destroy_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY),
-
-    'netif_be_driver_status_changed_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED),
-
-    'netif_fe_driver_status_changed_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED),
-
-    'netif_fe_interface_connect_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT),
-
-    'netif_fe_interface_status_changed_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED),
-    }
-
-msg_formats.update(netif_formats)
-
-#============================================================================
-CMSG_SHUTDOWN = 6
-
-CMSG_SHUTDOWN_POWEROFF  = 0
-CMSG_SHUTDOWN_REBOOT    = 1
-CMSG_SHUTDOWN_SUSPEND   = 2
-
-STOPCODE_shutdown       = 0
-STOPCODE_reboot         = 1
-STOPCODE_suspend        = 2
-
-shutdown_formats = {
-    'shutdown_poweroff_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_POWEROFF),
-    
-    'shutdown_reboot_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_REBOOT),
-
-    'shutdown_suspend_t':
-    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SUSPEND),
-    }
-
-msg_formats.update(shutdown_formats)
-
-#============================================================================
-
-class Msg:
-    pass
-
-def packMsg(ty, params):
-    if DEBUG: print '>packMsg', ty, params
-    (major, minor) = msg_formats[ty]
-    args = {}
-    for (k, v) in params.items():
-        if k == 'mac':
-            for i in range(0, 6):
-                args['mac[%d]' % i] = v[i]
-        else:
-            args[k] = v
-    if DEBUG:
-        for (k, v) in args.items():
-            print 'packMsg>', k, v, type(v)
-    msgid = 0
-    msg = xu.message(major, minor, msgid, args)
-    return msg
-
-def unpackMsg(ty, msg):
-    args = msg.get_payload()
-    mac = [0, 0, 0, 0, 0, 0]
-    macs = []
-    for (k, v) in args.items():
-        if k.startswith('mac['):
-            macs += k
-            i = int(k[4:5])
-            mac[i] = v
-        else:
-            pass
-    if macs:
-        args['mac'] = mac
-        for k in macs:
-            del args[k]
-    if DEBUG: print '<unpackMsg', ty, args
-    return args
-
-def msgTypeName(ty, subty):
-    for (name, info) in msg_formats.items():
-        if info[0] == ty and info[1] == subty:
-            return name
-    return None
-
diff --git a/tools/xen/lib/xend/server/netif.py b/tools/xen/lib/xend/server/netif.py
deleted file mode 100755 (executable)
index 2b01805..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-import random
-
-from twisted.internet import defer
-
-from xen.xend import sxp
-from xen.xend import PrettyPrint
-from xen.xend import Vifctl
-
-import channel
-import controller
-from messages import *
-
-class NetifControllerFactory(controller.ControllerFactory):
-    """Factory for creating network interface controllers.
-    Also handles the 'back-end' channel to the device driver domain.
-    """
-
-    def __init__(self):
-        controller.ControllerFactory.__init__(self)
-
-        self.majorTypes = [ CMSG_NETIF_BE ]
-
-        self.subTypes = {
-            CMSG_NETIF_BE_CREATE : self.recv_be_create,
-            CMSG_NETIF_BE_CONNECT: self.recv_be_connect,
-            CMSG_NETIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
-            }
-        self.attached = 1
-        self.registerChannel()
-
-    def createInstance(self, dom, recreate=0):
-        """Create or find the network interface controller for a domain.
-        """
-        #print 'netif>createInstance> dom=', dom
-        netif = self.getInstanceByDom(dom)
-        if netif is None:
-            netif = NetifController(self, dom)
-            self.addInstance(netif)
-        return netif
-
-    def getDomainDevices(self, dom):
-        netif = self.getInstanceByDom(dom)
-        return (netif and netif.getDevices()) or []
-
-    def getDomainDevice(self, dom, vif):
-        netif = self.getInstanceByDom(dom)
-        return (netif and netif.getDevice(vif)) or None
-        
-    def setControlDomain(self, dom, recreate=0):
-        """Set the 'back-end' device driver domain.
-        """
-        if self.dom == dom: return
-        self.deregisterChannel()
-        if not recreate:
-            self.attached = 0
-        self.dom = dom
-        self.registerChannel()
-        #
-        #if xend.netif.be_port.remote_dom != 0:
-        #    xend.netif.recovery = True
-        #    xend.netif.be_port = xend.main.port_from_dom(dom)
-        #
-
-    def getControlDomain(self):
-        return self.dom
-
-    def recv_be_create(self, msg, req):
-        self.callDeferred(0)
-    
-    def recv_be_connect(self, msg, req):
-        val = unpackMsg('netif_be_connect_t', msg)
-        dom = val['domid']
-        vif = val['netif_handle']
-        netif = self.getInstanceByDom(dom)
-        if netif:
-            netif.send_interface_connected(vif)
-        else:
-            print "recv_be_connect> unknown vif=", vif
-            pass
-
-    def recv_be_driver_status_changed(self, msg, req):
-        val = unpackMsg('netif_be_driver_status_changed_t', msg)
-        status = val['status']
-        if status == NETIF_DRIVER_STATUS_UP and not self.attached:
-            # If we are not attached the driver domain was changed, and
-            # this signals the new driver domain is ready.
-            for netif in self.getInstances():
-                netif.reattach_devices()
-            self.attached = 1
-
-##         pl = msg.get_payload()
-##         status = pl['status']
-##         if status == NETIF_DRIVER_STATUS_UP:
-##             if xend.netif.recovery:
-##                 print "New netif backend now UP, notifying guests:"
-##                 for netif_key in interface.list.keys():
-##                     netif = interface.list[netif_key]
-##                     netif.create()
-##                     print "  Notifying %d" % netif.dom
-##                     msg = xu.message(
-##                         CMSG_NETIF_FE,
-##                         CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
-##                         { 'handle' : 0, 'status' : 1 })
-##                     netif.ctrlif_tx_req(xend.main.port_from_dom(netif.dom),msg)
-##                 print "Done notifying guests"
-##                 recovery = False
-                
-class NetDev(controller.Dev):
-    """Info record for a network device.
-    """
-
-    def __init__(self, ctrl, vif, mac):
-        controller.Dev.__init__(self, ctrl)
-        self.vif = vif
-        self.mac = mac
-        self.evtchn = None
-        self.bridge = None
-        self.ipaddr = []
-
-    def sxpr(self):
-        vif = str(self.vif)
-        mac = self.get_mac()
-        val = ['netdev', ['vif', vif], ['mac', mac]]
-        if self.bridge:
-            val.append(['bridge', self.bridge])
-        if self.evtchn:
-            val.append(['evtchn',
-                        self.evtchn['port1'],
-                        self.evtchn['port2']])
-        return val
-
-    def get_vifname(self):
-        return "vif%d.%d" % (self.controller.dom, self.vif)
-
-    def get_mac(self):
-        return ':'.join(map(lambda x: "%x" % x, self.mac))
-
-    def vifctl_params(self):
-        return { 'mac'   : self.get_mac(),
-                 'bridge': self.bridge,
-                 'ipaddr': self.ipaddr }
-
-    def up(self, bridge=None, ipaddr=[]):
-        self.bridge = bridge
-        self.ipaddr = ipaddr
-        Vifctl.up(self.get_vifname(), **self.vifctl_params())
-
-    def down(self):
-        Vifctl.down(self.get_vifname(), **self.vifctl_params())
-
-    def destroy(self):
-        def cb_destroy(val):
-            self.controller.send_be_destroy(self.vif)
-        print 'NetDev>destroy>', 'vif=', self.vif
-        PrettyPrint.prettyprint(self.sxpr())
-        self.down()
-        d = self.controller.factory.addDeferred()
-        d.addCallback(cb_destroy)
-        self.controller.send_be_disconnect(self.vif)
-        #self.controller.send_be_destroy(self.vif)
-        
-
-class NetifController(controller.Controller):
-    """Network interface controller. Handles all network devices for a domain.
-    """
-    
-    def __init__(self, factory, dom):
-        #print 'NetifController> dom=', dom
-        controller.Controller.__init__(self, factory, dom)
-        self.devices = {}
-        
-        self.majorTypes = [ CMSG_NETIF_FE ]
-
-        self.subTypes = {
-            CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
-                self.recv_fe_driver_status_changed,
-            CMSG_NETIF_FE_INTERFACE_CONNECT    :
-                self.recv_fe_interface_connect,
-            }
-        self.registerChannel()
-        #print 'NetifController<', 'dom=', self.dom, 'idx=', self.idx
-
-    def sxpr(self):
-        val = ['netif', ['dom', self.dom]]
-        return val
-    
-    def randomMAC(self):
-        # VIFs get a random MAC address with a "special" vendor id.
-        # 
-        # NB. The vendor is currently an "obsolete" one that used to belong
-        # to DEC (AA-00-00). Using it is probably a bit rude :-)
-        # 
-        # NB2. The first bit of the first random octet is set to zero for
-        # all dynamic MAC addresses. This may allow us to manually specify
-        # MAC addresses for some VIFs with no fear of clashes.
-        mac = [ 0xaa, 0x00, 0x00,
-                random.randint(0x00, 0x7f),
-                random.randint(0x00, 0xff),
-                random.randint(0x00, 0xff) ]
-        return mac
-
-    def lostChannel(self):
-        print 'NetifController>lostChannel>', 'dom=', self.dom
-        #self.destroyDevices()
-        controller.Controller.lostChannel(self)
-
-    def getDevices(self):
-        return self.devices.values()
-
-    def getDevice(self, vif):
-        return self.devices.get(vif)
-
-    def addDevice(self, vif, vmac):
-        if vmac is None:
-            mac = self.randomMAC()
-        else:
-            mac = [ int(x, 16) for x in vmac.split(':') ]
-        if len(mac) != 6: raise ValueError("invalid mac")
-        #print "attach_device>", "vif=", vif, "mac=", mac
-        dev = NetDev(self, vif, mac)
-        self.devices[vif] = dev
-        return dev
-
-    def destroy(self):
-        print 'NetifController>destroy>', 'dom=', self.dom
-        self.destroyDevices()
-        
-    def destroyDevices(self):
-        for dev in self.getDevices():
-            dev.destroy()
-
-    def attachDevice(self, vif, vmac, recreate=0):
-        """Attach a network device.
-        If vmac is None a random mac address is assigned.
-
-        @param vif interface index
-        @param vmac mac address (string)
-        """
-        self.addDevice(vif, vmac)
-        if recreate:
-            d = defer.Deferred()
-            d.callback(self)
-        else:
-            d = self.factory.addDeferred()
-            self.send_be_create(vif)
-        return d
-
-    def reattach_devices(self):
-        """Reattach all devices when the back-end control domain has changed.
-        """
-        d = self.factory.addDeferred()
-        self.send_be_create(vif)
-        self.attach_fe_devices(0)
-
-    def attach_fe_devices(self):
-        for dev in self.devices.values():
-            msg = packMsg('netif_fe_interface_status_changed_t',
-                          { 'handle' : dev.vif,
-                            'status' : NETIF_INTERFACE_STATUS_DISCONNECTED,
-                            'evtchn' : 0,
-                            'mac'    : dev.mac })
-            self.writeRequest(msg)
-    
-    def recv_fe_driver_status_changed(self, msg, req):
-        if not req: return
-        msg = packMsg('netif_fe_driver_status_changed_t',
-                      { 'status'        : NETIF_DRIVER_STATUS_UP,
-                        'nr_interfaces' : len(self.devices) })
-        self.writeRequest(msg)
-        self.attach_fe_devices()
-
-    def recv_fe_interface_connect(self, msg, req):
-        val = unpackMsg('netif_fe_interface_connect_t', msg)
-        dev = self.devices[val['handle']]
-        dev.evtchn = channel.eventChannel(0, self.dom)
-        msg = packMsg('netif_be_connect_t',
-                      { 'domid'          : self.dom,
-                        'netif_handle'   : dev.vif,
-                        'evtchn'         : dev.evtchn['port1'],
-                        'tx_shmem_frame' : val['tx_shmem_frame'],
-                        'rx_shmem_frame' : val['rx_shmem_frame'] })
-        self.factory.writeRequest(msg)
-
-    def send_interface_connected(self, vif):
-        dev = self.devices[vif]
-        msg = packMsg('netif_fe_interface_status_changed_t',
-                      { 'handle' : dev.vif,
-                        'status' : NETIF_INTERFACE_STATUS_CONNECTED,
-                        'evtchn' : dev.evtchn['port2'],
-                        'mac'    : dev.mac })
-        self.writeRequest(msg)
-
-    def send_be_create(self, vif):
-        dev = self.devices[vif]
-        msg = packMsg('netif_be_create_t',
-                      { 'domid'        : self.dom,
-                        'netif_handle' : dev.vif,
-                        'mac'          : dev.mac })
-        self.factory.writeRequest(msg)
-
-    def send_be_disconnect(self, vif):
-        dev = self.devices[vif]
-        msg = packMsg('netif_be_disconnect_t',
-                      { 'domid'        : self.dom,
-                        'netif_handle' : dev.vif })
-        self.factory.writeRequest(msg)
-
-    def send_be_destroy(self, vif):
-        print 'NetifController>send_be_destroy>', 'dom=', self.dom, 'vif=', vif
-        PrettyPrint.prettyprint(self.sxpr())
-        dev = self.devices[vif]
-        del self.devices[vif]
-        msg = packMsg('netif_be_destroy_t',
-                      { 'domid'        : self.dom,
-                        'netif_handle' : vif })
-        self.factory.writeRequest(msg)
diff --git a/tools/xen/lib/xend/server/params.py b/tools/xen/lib/xend/server/params.py
deleted file mode 100644 (file)
index 7949f14..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# The following parameters could be placed in a configuration file.
-PID_FILE  = '/var/run/xend.pid'
-LOG_FILE  = '/var/log/xend.log'
-USER = 'root'
-CONTROL_DIR  = '/var/run/xend'
-MGMT_SOCK    = 'xendsock' # relative to CONTROL_DIR
-EVENT_PORT = 8001
-
-CONSOLE_PORT_BASE = 9600
-
diff --git a/tools/xen/lib/xend/sxp.py b/tools/xen/lib/xend/sxp.py
deleted file mode 100644 (file)
index 01654a2..0000000
+++ /dev/null
@@ -1,580 +0,0 @@
-#!/usr/bin/python2
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""
-Input-driven parsing for s-expression (sxp) format.
-Create a parser: pin = Parser();
-Then call pin.input(buf) with your input.
-Call pin.input_eof() when done.
-Use pin.read() to see if a value has been parsed, pin.get_val()
-to get a parsed value. You can call ready and get_val at any time -
-you don't have to wait until after calling input_eof.
-
-"""
-from __future__ import generators
-
-import sys
-import types
-import errno
-import string
-from StringIO import StringIO
-
-__all__ = [
-    "mime_type", 
-    "ParseError", 
-    "Parser", 
-    "atomp", 
-    "show", 
-    "show_xml", 
-    "elementp", 
-    "name", 
-    "attributes", 
-    "attribute", 
-    "children", 
-    "child", 
-    "child_at", 
-    "child0", 
-    "child1", 
-    "child2", 
-    "child3", 
-    "child4", 
-    "child_value", 
-    "has_id", 
-    "with_id", 
-    "child_with_id", 
-    "elements", 
-    "parse", 
-    ]
-
-mime_type = "application/sxp"
-
-escapes = {
-    'a': '\a',
-    'b': '\b',
-    't': '\t',
-    'n': '\n',
-    'v': '\v',
-    'f': '\f',
-    'r': '\r',
-    '\\': '\\',
-    '\'': '\'',
-    '\"': '\"'}
-
-k_list_open  = "("
-k_list_close = ")"
-k_attr_open  = "@"
-k_eval       = "!"
-
-escapes_rev = {}
-for k in escapes:
-    escapes_rev[escapes[k]] = k
-
-class ParseError(StandardError):
-
-    def __init__(self, parser, value):
-        self.parser = parser
-        self.value = value
-
-    def __str__(self):
-        return self.value
-
-class ParserState:
-
-    def __init__(self, fn, parent=None):
-        self.parent = parent
-        self.buf = ''
-        self.val = []
-        self.delim = None
-        self.fn = fn
-
-    def push(self, fn):
-        return ParserState(fn, parent=self)
-    
-class Parser:
-
-    def __init__(self):
-        self.error = sys.stderr
-        self.reset()
-
-    def reset(self):
-        self.val = []
-        self.eof = 0
-        self.err = 0
-        self.line_no = 0
-        self.char_no = 0
-        self.state = None
-
-    def push_state(self, fn):
-        self.state = self.state.push(fn)
-
-    def pop_state(self):
-        val = self.state
-        self.state = self.state.parent
-        if self.state and self.state.fn == self.state_start:
-            # Return to start state - produce the value.
-            self.val += self.state.val
-            self.state.val = []
-        return val
-
-    def in_class(self, c, s):
-        return s.find(c) >= 0
-        
-    def in_space_class(self, c):
-        return self.in_class(c, ' \t\n\v\f\r')
-
-    def is_separator(self, c):
-        return self.in_class(c, '{}()<>[]!;')
-
-    def in_comment_class(self, c):
-        return self.in_class(c, '#')
-
-    def in_string_quote_class(self, c):
-        return self.in_class(c, '"\'')
-
-    def in_printable_class(self, c):
-        return self.in_class(c, string.printable)
-
-    def set_error_stream(self, error):
-        self.error = error
-
-    def has_error(self):
-        return self.err > 0
-
-    def at_eof(self):
-        return self.eof
-
-    def input_eof(self):
-        self.eof = 1
-        self.input_char(-1)
-
-    def input(self, buf):
-        if not buf or len(buf) == 0:
-            self.input_eof()
-        else:
-            for c in buf:
-                self.input_char(c)
-
-    def input_char(self, c):
-        if self.at_eof():
-            pass
-        elif c == '\n':
-            self.line_no += 1
-            self.char_no = 0
-        else:
-           self.char_no += 1 
-
-        if self.state is None:
-            self.begin_start(None)
-        self.state.fn(c)
-
-    def ready(self):
-        return len(self.val) > 0
-
-    def get_val(self):
-        v = self.val[0]
-        self.val = self.val[1:]
-        return v
-
-    def get_all(self):
-        return self.val
-
-    def begin_start(self, c):
-        self.state = ParserState(self.state_start)
-
-    def end_start(self):
-        self.val += self.state.val
-        self.pop_state()
-    
-    def state_start(self, c):
-        if self.at_eof():
-            self.end_start()
-        elif self.in_space_class(c):
-            pass
-        elif self.in_comment_class(c):
-            self.begin_comment(c)
-        elif c == k_list_open:
-            self.begin_list(c)
-        elif c == k_list_close:
-            raise ParseError(self, "syntax error: "+c)
-        elif self.in_string_quote_class(c):
-            self.begin_string(c)
-        elif self.in_printable_class(c):
-            self.begin_atom(c)
-        elif c == chr(4):
-            # ctrl-D, EOT: end-of-text.
-            self.input_eof()
-        else:
-            raise ParseError(self, "invalid character: code %d" % ord(c))
-
-    def begin_comment(self, c):
-        self.push_state(self.state_comment)
-        self.state.buf += c
-
-    def end_comment(self):
-        self.pop_state()
-    
-    def state_comment(self, c):
-        if c == '\n' or self.at_eof():
-            self.end_comment()
-        else:
-            self.state.buf += c
-
-    def begin_string(self, c):
-        self.push_state(self.state_string)
-        self.state.delim = c
-
-    def end_string(self):
-        val = self.state.buf
-        self.state.parent.val.append(val)
-        self.pop_state()
-        
-    def state_string(self, c):
-        if self.at_eof():
-            raise ParseError(self, "unexpected EOF")
-        elif c == self.state.delim:
-            self.end_string()
-        elif c == '\\':
-            self.push_state(self.state_escape)
-        else:
-            self.state.buf += c
-
-    def state_escape(self, c):
-        if self.at_eof():
-            raise ParseError(self, "unexpected EOF")
-        d = escapes.get(c)
-        if d:
-            self.state.parent.buf += d
-            self.pop_state()
-        elif c == 'x':
-            self.state.fn = self.state_hex
-            self.state.val = 0
-        else:
-            self.state.fn = self.state_octal
-            self.state.val = 0
-            self.input_char(c)
-
-    def state_octal(self, c):
-        def octaldigit(c):
-            self.state.val *= 8
-            self.state.val += ord(c) - ord('0')
-            self.state.buf += c
-            if self.state.val < 0 or self.state.val > 0xff:
-                raise ParseError(self, "invalid octal escape: out of range " + self.state.buf)
-            if len(self.state.buf) == 3:
-               octaldone()
-               
-        def octaldone():
-            d = chr(self.state.val)
-            self.state.parent.buf += d
-            self.pop_state()
-            
-        if self.at_eof():
-            raise ParseError(self, "unexpected EOF")
-        elif '0' <= c <= '7':
-            octaldigit(c)
-        elif len(self.buf):
-            octaldone()
-            self.input_char(c)
-
-    def state_hex(self, c):
-        def hexdone():
-            d = chr(self.state.val)
-            self.state.parent.buf += d
-            self.pop_state()
-            
-        def hexdigit(c, d):
-            self.state.val *= 16
-            self.state.val += ord(c) - ord(d)
-            self.state.buf += c
-            if self.state.val < 0 or self.state.val > 0xff:
-                raise ParseError(self, "invalid hex escape: out of range " + self.state.buf)
-            if len(self.state.buf) == 2:
-                hexdone()
-            
-        if self.at_eof():
-            raise ParseError(self, "unexpected EOF")
-        elif '0' <= c <= '9':
-            hexdigit(c, '0')
-        elif 'A' <= c <= 'F':
-            hexdigit(c, 'A')
-        elif 'a' <= c <= 'f':
-            hexdigit(c, 'a')
-        elif len(buf):
-            hexdone()
-            self.input_char(c)
-
-    def begin_atom(self, c):
-        self.push_state(self.state_atom)
-        self.state.buf = c
-
-    def end_atom(self):
-        val = self.state.buf
-        self.state.parent.val.append(val)
-        self.pop_state()
-    
-    def state_atom(self, c):
-        if self.at_eof():
-            self.end_atom()
-        elif (self.is_separator(c) or
-              self.in_space_class(c) or
-              self.in_comment_class(c)):
-            self.end_atom()
-            self.input_char(c)
-        else:
-            self.state.buf += c
-
-    def begin_list(self, c):
-        self.push_state(self.state_list)
-
-    def end_list(self):
-        val = self.state.val
-        self.state.parent.val.append(val)
-        self.pop_state()
-
-    def state_list(self, c):
-        if self.at_eof():
-            raise ParseError(self, "unexpected EOF")
-        elif c == k_list_close:
-            self.end_list()
-        else:
-            self.state_start(c)
-
-def atomp(sxpr):
-    if sxpr.isalnum() or sxpr == '@':
-        return 1
-    for c in sxpr:
-        if c in string.whitespace: return 0
-        if c in '"\'\\(){}[]<>$#&%^': return 0
-        if c in string.ascii_letters: continue
-        if c in string.digits: continue
-        if c in '.-_:/~': continue
-        return 0
-    return 1
-    
-def show(sxpr, out=sys.stdout):
-    if isinstance(sxpr, types.ListType):
-        out.write(k_list_open)
-        i = 0
-        for x in sxpr:
-            if i: out.write(' ')
-            show(x, out)
-            i += 1
-        out.write(k_list_close)
-    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
-        out.write(sxpr)
-    else:
-        #out.write("'" + str(sxpr) + "'")
-        out.write(repr(str(sxpr)))
-
-def show_xml(sxpr, out=sys.stdout):
-    if isinstance(sxpr, types.ListType):
-        element = name(sxpr)
-        out.write('<%s' % element)
-        for attr in attributes(sxpr):
-            out.write(' %s=%s' % (attr[0], attr[1]))
-        out.write('>')
-        i = 0
-        for x in children(sxpr):
-            if i: out.write(' ')
-            show_xml(x, out)
-            i += 1
-        out.write('</%s>' % element)
-    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
-        out.write(sxpr)
-    else:
-        out.write(str(sxpr))
-
-def elementp(sxpr, elt=None):
-    return (isinstance(sxpr, types.ListType)
-            and len(sxpr)
-            and (None == elt or sxpr[0] == elt))
-
-def name(sxpr):
-    val = None
-    if isinstance(sxpr, types.StringType):
-        val = sxpr
-    elif isinstance(sxpr, types.ListType) and len(sxpr):
-        val = sxpr[0]
-    return val
-
-def attributes(sxpr):
-    val = []
-    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
-        attr = sxpr[1]
-        if elementp(attr, k_attr_open):
-            val = attr[1:]
-    return val
-
-def attribute(sxpr, key, val=None):
-    for x in attributes(sxpr):
-        if x[0] == key:
-            val = x[1]
-            break
-    return val
-
-def children(sxpr, elt=None):
-    val = []
-    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
-        i = 1
-        x = sxpr[i]
-        if elementp(x, k_attr_open):
-            i += 1
-        val = sxpr[i : ]
-    if elt:
-        def iselt(x):
-            return elementp(x, elt)
-        val = filter(iselt, val)
-    return val
-
-def child(sxpr, elt, val=None):
-    for x in children(sxpr):
-        if elementp(x, elt):
-            val = x
-            break
-    return val
-
-def child_at(sxpr, index, val=None):
-    kids = children(sxpr)
-    if len(kids) > index:
-        val = kids[index]
-    return val
-
-def child0(sxpr, val=None):
-    return child_at(sxpr, 0, val)
-
-def child1(sxpr, val=None):
-    return child_at(sxpr, 1, val)
-
-def child2(sxpr, val=None):
-    return child_at(sxpr, 2, val)
-
-def child3(sxpr, val=None):
-    return child_at(sxpr, 3, val)
-
-def child4(sxpr, val=None):
-    return child_at(sxpr, 4, val)
-
-def child_value(sxpr, elt, val=None):
-    kid = child(sxpr, elt)
-    if kid:
-        val = child_at(kid, 0, val)
-    return val
-
-def has_id(sxpr, id):
-    """Test if an s-expression has a given id.
-    """
-    return attribute(sxpr, 'id') == id
-
-def with_id(sxpr, id, val=None):
-    """Find the first s-expression with a given id, at any depth.
-
-    sxpr   s-exp or list
-    id     id
-    val    value if not found (default None)
-
-    return s-exp or val
-    """
-    if isinstance(sxpr, types.ListType):
-        for n in sxpr:
-            if has_id(n, id):
-                val = n
-                break
-            v = with_id(n, id)
-            if v is None: continue
-            val = v
-            break
-    return val
-
-def child_with_id(sxpr, id, val=None):
-    """Find the first child with a given id.
-
-    sxpr   s-exp or list
-    id     id
-    val    value if not found (default None)
-
-    return s-exp or val
-    """
-    if isinstance(sxpr, types.ListType):
-        for n in sxpr:
-            if has_id(n, id):
-                val = n
-                break
-    return val
-
-def elements(sxpr, ctxt=None):
-    """Generate elements (at any depth).
-    Visit elements in pre-order.
-    Values generated are (node, context)
-    The context is None if there is no parent, otherwise
-    (index, parent, context) where index is the node's index w.r.t its parent,
-    and context is the parent's context.
-
-    sxpr   s-exp
-
-    returns generator
-    """
-    yield (sxpr, ctxt)
-    i = 0
-    for n in children(sxpr):
-        if isinstance(n, types.ListType):
-            # Calling elements() recursively does not generate recursively,
-            # it just returns a generator object. So we must iterate over it.
-            for v in elements(n, (i, sxpr, ctxt)):
-                yield v
-        i += 1
-
-def to_string(sxpr):
-    """Convert an sxpr to a string.
-
-    sxpr sxpr
-    returns string
-    """
-    io = StringIO()
-    show(sxpr, io)
-    io.seek(0)
-    val = io.getvalue()
-    io.close()
-    return val
-
-def from_string(str):
-    """Create an sxpr by parsing a string.
-
-    str string
-    returns sxpr
-    """
-    io = StringIO(str)
-    return parse(io)
-
-def parse(io):
-    """Completely parse all input from 'io'.
-
-    io input file object
-    returns list of values, None if incomplete
-    raises ParseError on parse error
-    """
-    pin = Parser()
-    while 1:
-        buf = io.readline()
-        pin.input(buf)
-        if len(buf) == 0:
-            break
-    if pin.ready():
-        val = pin.get_all()
-    else:
-        val = None
-    return val
-   
-
-if __name__ == '__main__':
-    print ">main"
-    pin = Parser()
-    while 1:
-        buf = sys.stdin.read(1024)
-        #buf = sys.stdin.readline()
-        pin.input(buf)
-        while pin.ready():
-            val = pin.get_val()
-            print
-            print '****** val=', val
-        if len(buf) == 0:
-            break
-
diff --git a/tools/xen/lib/xm/__init__.py b/tools/xen/lib/xm/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/tools/xen/lib/xm/create.py b/tools/xen/lib/xm/create.py
deleted file mode 100644 (file)
index 12e2e80..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Domain creation.
-"""
-import string
-import sys
-
-from xen.xend import sxp
-from xen.xend import PrettyPrint
-from xen.xend.XendClient import server
-
-from xen.xm.opts import *
-
-gopts = Opts(use="""[options]
-
-Create a domain.
-""")
-
-gopts.opt('help', short='h',
-         fn=set_true, default=0,
-         use="Print this help.")
-
-gopts.opt('quiet', short='q',
-         fn=set_true, default=0,
-         use="Quiet.")
-
-gopts.opt('path', val='PATH',
-         fn=set_value, default='.:/etc/xen',
-         use="Search path for default scripts.")
-
-gopts.opt('defaults', short='f', val='FILE',
-         fn=set_value, default='xmdefaults',
-         use="Use the given default script.")
-
-gopts.opt('config', short='F', val='FILE',
-         fn=set_value, default=None,
-         use='Domain configuration to use (SXP).')
-
-gopts.opt('load', short='L', val='FILE',
-          fn=set_value, default=None,
-          use='Domain saved state to load.')
-
-gopts.opt('define', short='D', val='VAR=VAL',
-         fn=set_var, default=None,
-         use="""Set a variable before loading defaults, e.g. '-D vmid=3'
-         to set vmid. May be repeated to set more thanone variable.""")
-
-gopts.opt('dryrun', short='n',
-         fn=set_true, default=0,
-         use="Dry run - print the config but don't create the domain.")
-
-gopts.opt('name', short='N', val='NAME',
-          fn=set_value, default=None,
-          use="Domain name.")
-
-gopts.opt('console', short='c',
-         fn=set_true, default=0,
-         use="Connect to console after domain is created.")
-
-gopts.opt('kernel', short='k', val='FILE',
-         fn=set_value, default=None,
-         use="Path to kernel image.")
-
-gopts.opt('ramdisk', short='r', val='FILE',
-         fn=set_value, default='',
-         use="Path to ramdisk.")
-
-gopts.opt('builder', short='b', val='FUNCTION',
-         fn=set_value, default='linux',
-         use="Function to use to build the domain.")
-
-gopts.opt('memory', short='m', val='MEMORY',
-         fn=set_value, default=128,
-         use="Domain memory in MB.")
-
-gopts.opt('blkif',
-          fn=set_true, default=0,
-          use="Make the domain a block device backend.")
-
-gopts.opt('netif',
-          fn=set_true, default=0,
-          use="Make the domain a network interface backend.")
-
-gopts.opt('disk', short='d', val='phy:DEV,VDEV,MODE',
-         fn=append_value, default=[],
-         use="""Add a disk device to a domain. The physical device is DEV, which
-         is exported to the domain as VDEV. The disk is read-only if MODE
-         is 'r', read-write if MODE is 'w'.
-         The option may be repeated to add more than one disk.
-         """)
-
-gopts.opt('pci', val='BUS,DEV,FUNC',
-         fn=append_value, default=[],
-         use="""Add a PCI device to a domain, using given params (in hex).
-         For example '-pci c0,02,1a'.
-         The option may be repeated to add more than one pci device.
-         """)
-
-gopts.opt('ipaddr', short='i', val="IPADDR",
-         fn=append_value, default=[],
-         use="Add an IP address to the domain.")
-
-gopts.opt('vif', val="mac=MAC,bridge=BRIDGE",
-         fn=append_value, default=[],
-         use="""Add a network interface with the given MAC address and bridge.
-         If mac is not specified a random MAC address is used.
-         If bridge is not specified the default bridge is used.
-         This option may be repeated to add more than one vif.
-         Specifying vifs will increase the number of interfaces as needed.
-         """)
-
-gopts.opt('nics', val="NUM",
-         fn=set_int, default=1,
-         use="""Set the number of network interfaces.
-         Use the vif option to define interface parameters, otherwise
-         defaults are used. Specifying vifs will increase the
-         number of interfaces as needed.
-         """)
-
-gopts.opt('root', short='R', val='DEVICE',
-         fn=set_value, default='',
-         use="""Set the root= parameter on the kernel command line.
-         Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
-
-gopts.opt('extra', short='E', val="ARGS",
-         fn=set_value, default='',
-         use="Set extra arguments to append to the kernel command line.")
-
-gopts.opt('ip', short='I', val='IPADDR',
-         fn=set_value, default='',
-         use="Set the kernel IP interface address.")
-
-gopts.opt('gateway', val="IPADDR",
-         fn=set_value, default='',
-         use="Set the kernel IP gateway.")
-
-gopts.opt('netmask', val="MASK",
-         fn=set_value, default = '',
-         use="Set the kernel IP netmask.")
-
-gopts.opt('hostname', val="NAME",
-         fn=set_value, default='',
-         use="Set the kernel IP hostname.")
-
-gopts.opt('interface', val="INTF",
-         fn=set_value, default="eth0",
-         use="Set the kernel IP interface name.")
-
-gopts.opt('dhcp', val="off|dhcp",
-         fn=set_value, default='off',
-         use="Set the kernel dhcp option.")
-
-gopts.opt('nfs_server', val="IPADDR",
-         fn=set_value, default=None,
-         use="Set the address of the NFS server for NFS root.")
-
-gopts.opt('nfs_root', val="PATH",
-         fn=set_value, default=None,
-         use="Set the path of the root NFS directory.")
-
-def strip(pre, s):
-    """Strip prefix 'pre' if present.
-    """
-    if s.startswith(pre):
-        return s[len(pre):]
-    else:
-        return s
-
-def configure_image(config, opts):
-    """Create the image config.
-    """
-    config_image = [ opts.builder ]
-    config_image.append([ 'kernel', os.path.abspath(opts.kernel) ])
-    if opts.ramdisk:
-        config_image.append([ 'ramdisk', os.path.abspath(opts.ramdisk) ])
-    if opts.cmdline_ip:
-        cmdline_ip = strip('ip=', opts.cmdline_ip)
-        config_image.append(['ip', cmdline_ip])
-    if opts.root:
-        cmdline_root = strip('root=', opts.root)
-        config_image.append(['root', cmdline_root])
-    if opts.extra:
-        config_image.append(['args', opts.extra])
-    config.append(['image', config_image ])
-    
-def configure_disks(config_devs, opts):
-    """Create the config for disks (virtual block devices).
-    """
-    for (uname, dev, mode) in opts.disk:
-        config_vbd = ['vbd',
-                      ['uname', uname],
-                      ['dev', dev ],
-                      ['mode', mode ] ]
-        config_devs.append(['device', config_vbd])
-
-def configure_pci(config_devs, opts):
-    """Create the config for pci devices.
-    """
-    for (bus, dev, func) in opts.pci:
-        config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
-        config_devs.append(['device', config_pci])
-
-def configure_vifs(config_devs, opts):
-    """Create the config for virtual network interfaces.
-    """
-    vifs = opts.vif
-    vifs_n = max(opts.nics, len(vifs))
-
-    for idx in range(0, vifs_n):
-        if idx < len(vifs):
-            d = vifs[idx]
-            mac = d.get('mac')
-            bridge = d.get('bridge')
-        else:
-            mac = None
-            bridge = None
-        config_vif = ['vif']
-        if mac:
-            config_vif.append(['mac', mac])
-        if bridge:
-            config_vif.append(['bridge', bridge])
-        config_devs.append(['device', config_vif])
-
-def configure_vfr(config, opts):
-     if not opts.ipaddr: return
-     config_vfr = ['vfr']
-     idx = 0 # No way of saying which IP is for which vif?
-     for ip in opts.ipaddr:
-         config_vfr.append(['vif', ['id', idx], ['ip', ip]])
-     config.append(config_vfr)
-
-
-def make_config(opts):
-    """Create the domain configuration.
-    """
-    
-    config = ['vm',
-              ['name', opts.name ],
-              ['memory', opts.memory ] ]
-    if opts.cpu:
-        config.append(['cpu', opts.cpu])
-    if opts.blkif:
-        config.append(['backend', ['blkif']])
-    if opts.netif:
-        config.append(['backend', ['netif']])
-    
-    configure_image(config, opts)
-    config_devs = []
-    configure_disks(config_devs, opts)
-    configure_pci(config_devs, opts)
-    configure_vifs(config_devs, opts)
-    config += config_devs
-    return config
-
-def preprocess_disk(opts):
-    if not opts.disk: return
-    disk = []
-    for v in opts.disk:
-        d = v.split(',')
-        if len(d) != 3:
-            opts.err('Invalid disk specifier: ' + v)
-        disk.append(d)
-    opts.disk = disk
-
-def preprocess_pci(opts):
-    if not opts.pci: return
-    pci = []
-    for v in opts.pci:
-        d = v.split(',')
-        if len(d) != 3:
-            opts.err('Invalid pci specifier: ' + v)
-        # Components are in hex: add hex specifier.
-        hexd = map(lambda v: '0x'+v, d)
-        pci.append(hexd)
-    opts.pci = pci
-
-def preprocess_vifs(opts):
-    if not opts.vif: return
-    vifs = []
-    for vif in opts.vif:
-        d = {}
-        a = vif.split(',')
-        for b in a:
-            (k, v) = b.strip().split('=')
-            k = k.strip()
-            v = v.strip()
-            if k not in ['mac', 'bridge']:
-                opts.err('Invalid vif specifier: ' + vif)
-            d[k] = v
-        vifs.append(d)
-    opts.vif = vifs
-
-def preprocess_ip(opts):
-    setip = (opts.hostname or opts.netmask
-             or opts.gateway or opts.dhcp or opts.interface)
-    if not setip: return
-    #if not opts
-    ip = (opts.ip
-          + ':'
-          + ':' + opts.gateway
-          + ':' + opts.netmask
-          + ':' + opts.hostname
-          + ':' + opts.interface
-          + ':' + opts.dhcp)
-    opts.cmdline_ip = ip
-
-def preprocess_nfs(opts):
-    if (opts.nfs_root or opts.nfs_server):
-        if (not opts.nfs_root) or (not opts.nfs_server):
-            opts.err('Must set nfs root and nfs server')
-    else:
-        return
-    nfs = 'nfsroot=' + opts.nfs_server + ':' + opts.nfs_root
-    opts.extra = nfs + ' ' + opts.extra
-    
-def preprocess(opts):
-    if not opts.kernel:
-        opts.err("No kernel specified")
-    preprocess_disk(opts)
-    preprocess_pci(opts)
-    preprocess_vifs(opts)
-    preprocess_ip(opts)
-    preprocess_nfs(opts)
-         
-def make_domain(opts, config):
-    """Create, build and start a domain.
-    Returns: [int] the ID of the new domain.
-    """
-    if opts.vals.load:
-        filename = os.path.abspath(opts.vals.load)
-        dominfo = server.xend_domain_restore(filename, config)
-    else:
-        dominfo = server.xend_domain_create(config)
-
-    dom = int(sxp.child_value(dominfo, 'id'))
-    console_info = sxp.child(dominfo, 'console')
-    if console_info:
-        console_port = int(sxp.child_value(console_info, 'port'))
-    else:
-        console_port = None
-    
-    if server.xend_domain_unpause(dom) < 0:
-        server.xend_domain_destroy(dom)
-        opts.err("Failed to start domain %d" % dom)
-    opts.info("Started domain %d, console on port %d"
-              % (dom, console_port))
-    return (dom, console_port)
-
-def main(argv):
-    opts = gopts
-    args = opts.parse(argv)
-    if opts.vals.help:
-        opts.usage()
-        return
-    if opts.vals.config:
-        pass
-    else:
-        opts.load_defaults()
-    preprocess(opts.vals)
-    config = make_config(opts.vals)
-    if opts.vals.dryrun:
-        PrettyPrint.prettyprint(config)
-    else:
-        make_domain(opts, config)
-        
-if __name__ == '__main__':
-    main(sys.argv)
diff --git a/tools/xen/lib/xm/main.py b/tools/xen/lib/xm/main.py
deleted file mode 100644 (file)
index 3ab5d23..0000000
+++ /dev/null
@@ -1,448 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Grand unified management application for Xen.
-"""
-import os
-import os.path
-import sys
-from getopt import getopt
-
-from xen.xend import PrettyPrint
-from xen.xend import sxp
-from xen.xend.XendClient import server
-from xen.xm import create, shutdown
-
-class Prog:
-    """Base class for sub-programs.
-    """
-
-    """Program group it belongs to"""
-    group = 'all'
-    """Program name."""
-    name = '??'
-    """Short program info."""
-    info = ''
-
-    def __init__(self, xm):
-        self.xm = xm
-
-    def err(self, msg):
-        self.xm.err(msg)
-
-    def help(self, args):
-        self.shortHelp(args)
-
-    def shortHelp(self, args):
-        print "%-14s %s" % (self.name, self.info)
-
-    def main(self, args):
-        """Program main entry point.
-        """
-        pass
-
-
-class ProgUnknown(Prog):
-
-    name = 'unknown'
-    info = ''
-    
-    def help(self, args):
-        self.xm.err("Unknown command: %s\nTry '%s help' for more information."
-                    % (args[0], self.xm.name))
-
-    main = help
-
-class Xm:
-    """Main application.
-    """
-
-    def __init__(self):
-        self.name = 'xm'
-        self.unknown = ProgUnknown(self)
-        self.progs = {}
-
-    def err(self, msg):
-        print >>sys.stderr, "Error:", msg
-        sys.exit(1)
-
-    def main(self, args):
-        """Main entry point. Dispatches to the progs.
-        """
-        self.name = args[0]
-        if len(args) < 2:
-            self.err("Missing command\nTry '%s help' for more information."
-                     % self.name)
-        help = self.helparg(args)
-        p = self.getprog(args[1], self.unknown)
-        if help:
-            p.help(args[1:])
-        else:
-            p.main(args[1:])
-
-    def helparg(self, args):
-        for a in args:
-            if a in ['-h', '--help']:
-                return 1
-        return 0
-
-    def prog(self, pklass):
-        """Add a sub-program.
-
-        pklass  program class (Prog subclass)
-        """
-        p = pklass(self)
-        self.progs[p.name] = p
-        return p
-
-    def getprog(self, name, val=None):
-        """Get a sub-program.
-        """
-        return self.progs.get(name, val)
-
-    def proglist(self):
-        """Get a list of sub-programs, ordered by group.
-        """
-        groups = {}
-        for p in self.progs.values():
-            l = groups.get(p.group, [])
-            l.append(p)
-            groups[p.group] = l
-        kl = groups.keys()
-        kl.sort()
-        pl = []
-        for k in kl:
-            l = groups[k]
-            l.sort()
-            pl += l
-        return pl
-        
-# Create the application object, then add the sub-program classes.
-xm = Xm()
-
-class ProgHelp(Prog):
-
-    name = "help"
-    info = "Print help."
-    
-    def help(self, args):
-        if len(args) == 2:
-            name = args[1]
-            p = self.xm.getprog(name)
-            if p:
-                p.help(args[1:])
-            else:
-                print '%s: Unknown command: %s' % (self.name, name)
-        else:
-            for p in self.xm.proglist():
-                p.shortHelp(args)
-            print "\nTry '%s help CMD' for help on CMD" % self.xm.name
-
-    main = help
-
-xm.prog(ProgHelp)
-
-class ProgCreate(Prog):
-
-    group = 'domain'
-    name = "create"
-    info = """Create a domain."""
-
-    def help(self, args):
-        create.main([args[0], '-h'])
-
-    def main(self, args):
-        create.main(args)
-
-xm.prog(ProgCreate)
-
-class ProgSave(Prog):
-    group = 'domain'
-    name = "save"
-    info = """Save domain state (and config) to file."""
-
-    def help(self, args):
-        print args[0], "DOM FILE"
-        print """\nSave domain with id DOM to FILE."""
-        
-    def main(self, args):
-        if len(args) < 3: self.err("%s: Missing arguments" % args[0])
-        dom = args[1]
-        savefile = os.path.abspath(args[2])
-        server.xend_domain_save(dom, savefile)
-
-xm.prog(ProgSave)
-
-class ProgRestore(Prog):
-    group = 'domain'
-    name = "restore"
-    info = """Create a domain from a saved state."""
-
-    def help(self, args):
-        print args[0], "FILE [CONFIG]"
-        print "\nRestore a domain from FILE using configuration CONFIG."
-    
-    def main(self, help, args):
-        if len(args) < 2: self.err("%s: Missing arguments" % args[0])
-        savefile =  os.path.abspath(args[1])
-        if len(args) >= 3:
-            configfile = os.path.abspath(args[2])
-        else:
-            configfile = None
-        info = server.xend_domain_restore(savefile, configfile)
-        PrettyPrint.prettyprint(info)
-
-xm.prog(ProgRestore)
-
-class ProgList(Prog):
-    group = 'domain'
-    name = "list"
-    info = """List info about domains."""
-
-    short_options = 'l'
-    long_options = ['long']
-
-    def help(self, args):
-        if help:
-            print args[0], '[options] [DOM...]'
-            print """\nGet information about domains.
-            Either all domains or the domains given.
-
-            -l, --long   Get more detailed information.
-            """
-            return
-        
-    def main(self, args):
-        use_long = 0
-        (options, params) = getopt(args[1:],
-                                   self.short_options,
-                                   self.long_options)
-        n = len(params)
-        for (k, v) in options:
-            if k in ['-l', '--long']:
-                use_long = 1
-                
-        if n == 0:
-            doms = map(int, server.xend_domains())
-            doms.sort()
-        else:
-            doms = map(int, params)
-            
-        if use_long:
-            self.long_list(doms)
-        else:
-            self.brief_list(doms)
-
-    def brief_list(self, doms):
-        print 'Dom  Name             Mem(MB)  CPU  State  Time(s)'
-        for dom in doms:
-            info = server.xend_domain(dom)
-            d = {}
-            d['dom'] = int(dom)
-            d['name'] = sxp.child_value(info, 'name', '??')
-            d['mem'] = int(sxp.child_value(info, 'memory', '0'))
-            d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
-            d['state'] = sxp.child_value(info, 'state', '??')
-            d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
-            print ("%(dom)-4d %(name)-16s %(mem)7d  %(cpu)3d  %(state)5s  %(cpu_time)7.1f" % d)
-
-    def long_list(self, doms):
-        for dom in doms:
-            info = server.xend_domain(dom)
-            print '\nDomain %d' % dom
-            PrettyPrint.prettyprint(info)
-
-xm.prog(ProgList)
-
-class ProgDestroy(Prog):
-    group = 'domain'
-    name = "destroy"
-    info = """Terminate a domain immediately."""
-
-    def help(self, args):
-        print args[0], 'DOM'
-        print '\nTerminate domain DOM immediately.'
-
-    def main(self, args):
-        if len(args) < 2: self.err("%s: Missing domain" % args[0])
-        dom = args[1]
-        server.xend_domain_destroy(dom)
-
-xm.prog(ProgDestroy)
-
-class ProgShutdown(Prog):
-    group = 'domain'
-    name = "shutdown"
-    info = """Shutdown a domain."""
-
-    def help(self, args):
-        shutdown.main([args[0], '-h'])
-    
-    def main(self, args):
-        shutdown.main(args)
-
-xm.prog(ProgShutdown)
-
-class ProgPause(Prog):
-    group = 'domain'
-    name = "pause"
-    info = """Pause execution of a domain."""
-
-    def help(self, args):
-        print args[0], 'DOM'
-        print '\nPause execution of domain DOM.'
-
-    def main(self, args):
-        if len(args) < 2: self.err("%s: Missing domain" % args[0])
-        dom = args[1]
-        server.xend_domain_pause(dom)
-
-xm.prog(ProgPause)
-
-class ProgUnpause(Prog):
-    group = 'domain'
-    name = "unpause"
-    info = """Unpause a paused domain."""
-
-    def help(self, args):
-        print args[0], 'DOM'
-        print '\nUnpause execution of domain DOM.'
-
-    def main(self, args):
-        if len(args) < 2: self.err("%s: Missing domain" % args[0])
-        dom = args[1]
-        server.xend_domain_unpause(dom)
-
-xm.prog(ProgUnpause)
-
-class ProgPincpu(Prog):
-    group = 'domain'
-    name = "pincpu"
-    info = """Pin a domain to a cpu. """
-
-    def help(self, args):
-        print args[0],'DOM CPU'
-        print '\nPin domain DOM to cpu CPU.'
-
-    def main(self, args):
-        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
-        v = map(int, args[1:3])
-        server.xend_domain_pincpu(*v)
-
-xm.prog(ProgPincpu)
-
-class ProgBvt(Prog):
-    group = 'scheduler'
-    name = "bvt"
-    info = """Set BVT scheduler parameters."""
-    
-    def help(self, args):
-        print args[0], "DOM MCUADV WARP WARPL WARPU"
-        print '\nSet Borrowed Virtual Time scheduler parameters.'
-
-    def main(self, args):
-        if len(args) != 6: self.err("%s: Invalid argument(s)" % args[0])
-        v = map(int, args[1:6])
-        server.xend_domain_cpu_bvt_set(*v)
-
-xm.prog(ProgBvt)
-
-class ProgBvtslice(Prog):
-    group = 'scheduler'
-    name = "bvtslice"
-    info = """Set the BVT scheduler slice."""
-
-    def help(self, args):
-        print args[0], 'SLICE'
-        print '\nSet Borrowed Virtual Time scheduler slice.'
-
-    def main(self, args):
-        if len(args) < 2: self.err('%s: Missing slice' % args[0])
-        server.xend_node_cpu_bvt_slice_set(slice)
-
-xm.prog(ProgBvtslice)
-
-class ProgAtropos(Prog):
-    group = 'scheduler'
-    name= "atropos"
-    info = """Set atropos parameters."""
-
-    def help(self, args):
-        print args[0], "DOM PERIOD SLICE LATENCY XTRATIME"
-        print "\nSet atropos parameters."
-
-    def main(self, args):
-        if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
-        v = map(int, args[1:5])
-        server.xend_domain_cpu_atropos_set(*v)
-
-xm.prog(ProgAtropos)
-
-class ProgRrobin(Prog):
-    group = 'scheduler'
-    name = "rrobin"
-    info = """Set round robin slice."""
-
-    def help(self, args):
-        print args[0], "SLICE"
-        print "\nSet round robin scheduler slice."
-
-    def main(self, args):
-        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
-        rrslice = int(args[1])
-        server.xend_node_rrobin_set(rrslice)
-
-xm.prog(ProgRrobin)
-
-class ProgInfo(Prog):
-    group = 'host'
-    name = "info"
-    info = """Get information about the xen host."""
-
-    def main(self, args):
-        info = server.xend_node()
-        for x in info[1:]:
-            print "%-23s:" % x[0], x[1]
-
-xm.prog(ProgInfo)
-
-class ProgConsoles(Prog):
-    group = 'console'
-    name = "consoles"
-    info = """Get information about domain consoles."""
-
-    def main(self, args):
-        l = server.xend_consoles()
-        print "Dom Port  Id"
-        for x in l:
-            info = server.xend_console(x)
-            d = {}
-            d['dom'] = sxp.child(info, 'dst', ['dst', '?', '?'])[1]
-            d['port'] = sxp.child_value(info, 'port', '?')
-            d['id'] = sxp.child_value(info, 'id', '?')
-            print "%(dom)3s %(port)4s %(id)3s" % d
-
-xm.prog(ProgConsoles)
-
-class ProgConsole(Prog):
-    group = 'console'
-    name = "console"
-    info = """Open a console to a domain."""
-    
-    def help(self, args):
-        print "console DOM"
-        print "\nOpen a console to domain DOM."
-
-    def main(self, args):
-        if len(args) < 2: self.err("%s: Missing domain" % args[0])
-        dom = args[1]
-        info = server.xend_domain(dom)
-        console = sxp.child(info, "console")
-        if not console:
-            self.err("No console information")
-        port = sxp.child_value(console, "port")
-        from xen.util import console_client
-        console_client.connect("localhost", int(port))
-
-xm.prog(ProgConsole)
-
-def main(args):
-    xm.main(args)
diff --git a/tools/xen/lib/xm/opts.py b/tools/xen/lib/xm/opts.py
deleted file mode 100644 (file)
index eb07936..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Object-oriented command-line option support.
-"""
-from getopt import getopt
-import os
-import os.path
-import sys
-import types
-
-class Opt:
-    """An individual option.
-    """
-    def __init__(self, opts, name, short=None, long=None,
-                 val=None, fn=None, use=None, default=None):
-        """Create an option.
-
-        opts    parent options object
-        name    name of the field it controls
-        short   short (1-char) command line switch (optional)
-        long    long command-line switch. Defaults to option name.
-        val     string used to print option args in help.
-                If val is not specified the option has no arg.
-        fn      function to call when the option is specified.
-        use     usage (help) string
-        default default value if not specified on command-line
-        """
-        self.opts = opts
-        self.name = name
-        self.short = short
-        if long is None:
-            long = name
-        self.long = long
-        self.val = val
-        self.use = use
-        self.default = default
-        self.optkeys = []
-        if self.short:
-            self.optkeys.append('-' + self.short)
-        if self.long:
-            self.optkeys.append('--' + self.long)
-        self.fn = fn
-        self.specified_opt = None
-        self.specified_val = None
-        self.value = None
-        self.set(default)
-
-    def __repr__(self):
-        return self.name + '=' + str(self.specified_val)
-
-    __str__ = __repr__
-
-    def set(self, value):
-        """Set the option value.
-        """
-        self.opts.setopt(self.name, value)
-
-    def get(self):
-        """Get the option value.
-        """
-        return self.opts.getopt(self.name)
-
-    def append(self, value):
-        """Append a value to the option value.
-        """
-        v = self.get() or []
-        v.append(value)
-        self.set(v)
-
-    def short_opt(self):
-        """Short option spec.
-        """
-        if self.short:
-            if self.val:
-                return self.short + ':'
-            else:
-                return self.short
-        else:
-            return None
-
-    def long_opt(self):
-        """Long option spec.
-        """
-        if self.long:
-            if self.val:
-                return self.long + '='
-            else:
-                return self.long
-        else:
-            return None
-
-    def show(self):
-        sep = ''
-        for x in self.optkeys:
-            print sep, x,
-            sep = ','
-        if self.val:
-            print self.val,
-        print
-        if self.use:
-            print '\t',
-            print self.use
-        if self.val:
-            print '\tDefault', self.default or 'None'
-
-    def specify(self, k, v):
-        """Specify the option. Called when the option is set
-        from the command line.
-
-        k  option switch used
-        v  optional value given (if any)
-        """
-        if k in self.optkeys:
-            if self.val is None and v:
-                self.opts.err("Option '%s' does not take a value" % k)
-            self.specified_opt = k
-            self.specified_val = v
-            if self.fn:
-                self.fn(self, k, v)
-            return 1
-        else:
-            return 0
-
-    def specified(self):
-        """Test whether the option has been specified: set
-        from the command line.
-        """
-        return self.specified_opt
-
-class OptVals:
-    """Class to hold option values.
-    """
-    pass
-
-class Opts:
-    """Container for options.
-    """
-    def __init__(self, use=None):
-        """Options constructor.
-
-        use  usage string
-        """
-        self.use = use
-        # List of options.
-        self.options = []
-        # Options indexed by name.
-        self.options_map = {}
-        # Command-line arguments.
-        self.argv = []
-        # Option values.
-        self.vals = OptVals()
-        self.vals.quiet = 0
-        # Variables for default scripts.
-        self.vars = {}
-
-    def __repr__(self):
-        return '\n'.join(map(str, self.options))
-
-    __str__ = __repr__
-
-    def opt(self, name, **args):
-        """Add an option.
-
-        name    option name
-        **args  keyword params for option constructor
-        """
-        x = Opt(self, name, **args)
-        self.options.append(x)
-        self.options_map[name] = x
-        return x
-
-    def setvar(self, var, val):
-        """Set a default script variable.
-        """
-        self.vars[var] = val
-
-    def getvar(self, var):
-        """Get a default script variable.
-        """
-        return self.vars.get(var)
-
-    def option(self, name):
-        """Get an option (object).
-        """
-        return self.options_map.get(name)
-
-    def setopt(self, name, val):
-        """Set an option value.
-        An option can also be set using 'opts.vals.name = val'.
-        """
-        setattr(self.vals, name, val)
-
-    def getopt(self, name):
-        """Get an option value.
-        An option value can also be got using 'opts.vals.name'.
-        """
-        getattr(self.vals, name)
-
-    def specified(self, name):
-        """Test if an option has been specified.
-        """
-        opt = self.option(name)
-        return opt and opt.specified()
-
-    def err(self, msg):
-        """Print an error to stderr and exit.
-        """
-        print >>sys.stderr, "Error:", msg
-        sys.exit(1)
-
-    def info(self, msg):
-        """Print a message to stdout (unless quiet is set).
-        """
-        if self.vals.quiet: return
-        print msg
-
-    def warn(self, msg):
-        """Print a warning to stdout.
-        """
-        print >>sys.stderr, "Warning:", msg
-
-    def parse(self, argv):
-        """Parse arguments argv using the options.
-
-        return remaining arguments
-        """
-        self.argv = argv
-        (vals, args) = getopt(argv[1:], self.short_opts(), self.long_opts())
-        self.args = args
-        for (k, v) in vals:
-            for opt in self.options:
-                if opt.specify(k, v): break
-            else:
-                print >>sys.stderr, "Error: Unknown option:", k
-                self.usage()
-        return args
-
-    def short_opts(self):
-        """Get short options specifier for getopt.
-        """
-        l = []
-        for x in self.options:
-            y = x.short_opt()
-            if not y: continue
-            l.append(y)
-        return ''.join(l)
-
-    def long_opts(self):
-        """Get long options specifier for getopt.
-        """
-        l = []
-        for x in self.options:
-            y = x.long_opt()
-            if not y: continue
-            l.append(y)
-        return l
-
-    def usage(self):
-        print 'Usage: ', self.argv[0], self.use or 'OPTIONS'
-        for opt in self.options:
-            opt.show()
-
-    def load_defaults(self):
-        """Load a defaults script. Assumes these options set:
-        'path'    search path
-        'default' script name
-        """
-        for x in [ '' ] + self.vals.path.split(':'):
-            if x:
-                p = os.path.join(x, self.vals.defaults)
-            else:
-                p = self.vals.defaults
-            if os.path.exists(p):
-                self.load(p)
-                break
-        else:
-            self.err("Cannot open defaults file %s" % self.vals.defaults)
-
-    def load(self, defaults, help=0):
-        """Load a defaults file. Local variables in the file
-        are used to set options with the same names.
-        Variables are not used to set options that are already specified.
-        """
-        # Create global and lobal dicts for the file.
-        # Initialize locals to the vars.
-        # Use exec to do the standard imports and
-        # define variables we are passing to the script.
-        globals = {}
-        locals = {}
-        locals.update(self.vars)
-        cmd = '\n'.join(["import sys",
-                         "import os",
-                         "import os.path",
-                         "import xen.util.ip",
-                         "xm_file = '%s'" % defaults,
-                         "xm_help = %d" % help ])
-        exec cmd in globals, locals
-        execfile(defaults, globals, locals)
-        if help: return
-        # Extract the values set by the script and set the corresponding
-        # options, if not set on the command line.
-        vtypes = [ types.StringType,
-                   types.ListType,
-                   types.IntType,
-                   types.FloatType
-                   ]
-        for (k, v) in locals.items():
-            if self.specified(k): continue
-            if not(type(v) in vtypes): continue
-            self.setopt(k, v)
-
-def set_true(opt, k, v):
-    """Set an option true."""
-    opt.set(1)
-
-def set_false(opt, k, v):
-    """Set an option false."""
-    opt.set(0)
-
-def set_value(opt, k, v):
-    """Set an option to a valoue."""
-    opt.set(v)
-
-def set_int(opt, k, v):
-    """Set an option to an integer value."""
-    try:
-        v = int(v)
-    except:
-        opt.opts.err('Invalid value: ' + str(v))
-    opt.set(v)
-
-def append_value(opt, k, v):
-    """Append a value to a list option."""
-    opt.append(v)
-
-def set_var(opt, k, v):
-    """Set a default script variable.
-    """
-    (var, val) = v.strip().split('=')
-    opt.opts.setvar(var.strip(), val.strip())
-
diff --git a/tools/xen/lib/xm/shutdown.py b/tools/xen/lib/xm/shutdown.py
deleted file mode 100644 (file)
index aaa3545..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-"""Domain shutdown.
-"""
-import string
-import sys
-import time
-
-from xen.xend.XendClient import server
-from xen.xm.opts import *
-
-gopts = Opts(use="""[options] [DOM]
-
-Shutdown one or more domains gracefully.""")
-
-gopts.opt('help', short='h',
-         fn=set_true, default=0,
-         use="Print this help.")
-
-gopts.opt('all', short='a',
-         fn=set_true, default=0,
-         use="Shutdown all domains.")
-
-gopts.opt('wait', short='w',
-         fn=set_true, default=0,
-         use='Wait for shutdown to complete.')
-
-gopts.opt('norestart', short='n',
-          fn=set_true, default=0,
-          use='Prevent domain restart.')
-
-def shutdown(opts, doms, wait):
-    def domains():
-        return [ int(a) for a in server.xend_domains() ]
-    if doms == None: doms = domains()
-    if 0 in doms:
-        doms.remove(0)
-    for d in doms:
-        server.xend_domain_shutdown(d)
-    if wait:
-        while doms:
-            alive = domains()
-            dead = []
-            for d in doms:
-                if d in alive: continue
-                dead.append(d)
-            for d in dead:
-                opts.info("Domain %d terminated" % d)
-                doms.remove(d)
-            time.sleep(1)
-        opts.info("All domains terminated")
-
-def main_all(opts, args):
-    shutdown(opts, None, opts.vals.wait)
-
-def main_dom(opts, args):
-    if len(args) < 1: opts.err('Missing domain')
-    dom = args[0]
-    try:
-        domid = int(dom)
-    except:
-        opts.err('Invalid domain: ' + dom)
-    shutdown(opts, [ domid ], opts.vals.wait)
-    
-def main(argv):
-    opts = gopts
-    args = opts.parse(argv)
-    if opts.vals.help:
-        opts.usage()
-        return
-    print 'shutdown.main>', len(args), args
-    if opts.vals.all:
-        main_all(opts, args)
-    else:
-        main_dom(opts, args)
-        
diff --git a/tools/xen/setup.py b/tools/xen/setup.py
deleted file mode 100644 (file)
index 1f0e959..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-
-from distutils.core import setup, Extension
-
-setup(name            = 'xen',
-      version         = '1.0',
-      description     = 'Xen',
-      author          = 'Mike Wray',
-      author_email    = 'mike.wray@hp.com',
-      packages        = ['xen',
-                         'xen.ext',
-                         'xen.util',
-                         'xen.xend',
-                         'xen.xend.server',
-                         'xen.xm',
-                         ],
-      package_dir     = { 'xen': 'lib' },
-      )
diff --git a/tools/xen/vifctl b/tools/xen/vifctl
deleted file mode 100644 (file)
index efd0b0b..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-#!/usr/bin/python
-#  -*- mode: python; -*-
-#============================================================================
-# Xen vif control script.
-#
-# vifctl init [bridge=<bridge>] [interface=<interface>]
-#
-#    Called when xend starts up. Default behaviour is to create <bridge>
-#    and add <interface> to it, moving its IP address to <bridge> and adjusting routes.
-#
-# vifctl (up|down) vif=<vif> mac=<mac> [bridge=<bridge>] (ipaddr=<ipaddr>)*
-#
-#    Called when a vif is brought up or down. Default behaviour is to add
-#    the vif to <bridge> on up and remove it from the bridge on down.
-#    If ipaddr is specified, iptables rules for the ip addresses are
-#    added on up and removed on down. The bridge a vif is added to can
-#    be set in the vm config.
-#
-# The default bridge is nbe-br.
-# The default interface is eth0.
-#
-#============================================================================
-
-import sys
-import types
-
-from xen.util import Brctl
-
-from xen.xend import XendRoot
-xroot = XendRoot.instance()
-
-class VifControl:
-
-    prefix = 'vifctl_'
-
-    DEFAULT_BRIDGE = 'nbe-br'
-    DEFAULT_INTERFACE = 'eth0'
-
-    def __init__(self):
-        self.name = 'vifctl'
-    
-    def main(self, args):
-        #print self.name, args
-        if len(args) < 2:
-            usage(args)
-        self.name = args[0]
-        cmd = self.prefix + args[1]
-        meth = getattr(self, cmd, self.unknown)
-        meth(args[1:])
-
-    def usage(self, args, out=sys.stderr):
-        print >>out, 'Missing command, try \n%s help' % self.name
-
-    def unknown(self, args, out=sys.stderr):
-        print >>out, 'Unknown command:', args[1]
-        self.help(out=out)
-        sys.exit(1)
-
-    def help(self, out=sys.stdout):
-        print >>out, 'Commands are:',
-        for x in vars(self):
-            if x.startswith(prefix):
-                cmd = x[len(prefix):]
-                print  >>out, cmd,
-        print >>out
-
-    def getparams(self, d, args, req=[]):
-        """Parse args of the form 'key=val'. Valid keys are the ones
-        in the dict 'd' passed in. If entries in 'd' have list values the
-        values of the keys are appended.
-
-        If 'req' is specified it is a list of required keys.
-        """
-        for x in args:
-            (k, v) = x.split('=')
-            k = k.strip()
-            v = v.strip()
-            if k not in d:
-                print >>sys.stderr, 'Invalid parameter: ', k
-                sys.exit(1)
-            vold = d[k]
-            if isinstance(vold , types.ListType):
-                d[k] = vold + v
-            else:
-                d[k] = v
-        for x in req:
-            if not d[x]:
-                print >>sys.stderr, 'Missing parameter:', x
-                sys.exit(1)
-        return d
-            
-    def vifctl_help(self, args):
-        self.help()
-
-    def default_bridge(self):
-        return xroot.get_config_value('bridge', self.DEFAULT_BRIDGE)
-
-    def default_interface(self):
-        return xroot.get_config_value('interface', self.DEFAULT_INTERFACE)
-    
-    def vifctl_init(self, args):
-        """Entry point for 'vifctl init'.
-        """
-        d = { 'bridge'   : self.default_bridge(),
-              'interface': self.default_interface() }
-        params = self.getparams(d, args[1:])
-        interface = params['interface']
-        bridge = params['bridge']
-        # Create bridge 'bridge'.
-        Brctl.bridge_create(bridge)
-        # Reconfigure so that 'interface' is added to 'bridge',
-        # and 'bridge' has the IP address from 'interface'.
-        Brctl.reconfigure(interface, bridge)
-        
-    def vifparams(self, args):
-        d = { 'vif'   : None,
-              'mac'   : None,
-              'bridge': self.default_bridge(),
-              'ipaddr': [] }
-        d = self.getparams(d, args, req=['vif', 'mac'])
-        return d
-
-    def vifctl_up(self, args):
-        """Entry point for 'vifctl up'.
-        """
-        params = self.vifparams(args[1:])
-        # Add the vif to its bridge.
-        Brctl.vif_bridge_add(params)
-        if params['ipaddr']:
-            # Add iptables rules for the ip addresses.
-            vif = params['vif']
-            for ipaddr in params['ipaddr']:
-               Brctl.vif_restrict_addr(vif, ipaddr)
-
-    def vifctl_down(self, args):
-        """Entry point for 'vifctl down'.
-        """
-        params = self.vifparams(args[1:])
-        # Remove the vif from its bridge.
-        Brctl.vif_bridge_rem(params)
-        if params['ip']:
-            # Remove iptables rules for the ip addresses.
-            vif = params['vif']
-            for ip in params['ip']:
-               Brctl.vif_restrict_addr(vif, ip, delete=1)
-
-
-if __name__ == "__main__":
-    VifControl().main(sys.argv)
diff --git a/tools/xen/xend b/tools/xen/xend
deleted file mode 100644 (file)
index 1e13e14..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/python
-#  -*- mode: python; -*-
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Xen management daemon. Lives in /usr/sbin.
-   Provides console server and HTTP management api.
-
-   Run:
-
-   xend start
-
-   The daemon is stopped with:
-
-   xend stop
-
-   The daemon should reconnect to device control interfaces
-   and recover its state when restarted.
-"""
-import os
-import sys
-from xen.xend.server import SrvDaemon
-
-def main():
-    daemon = SrvDaemon.instance()
-    if not sys.argv[1:]:
-        print 'usage: %s {start|stop|restart}' % sys.argv[0]
-    elif os.fork():
-        pid, status = os.wait()
-        return status >> 8
-    elif sys.argv[1] == 'start':
-        return daemon.start()
-    elif sys.argv[1] == 'trace_start':
-        return daemon.start(trace=1)
-    elif sys.argv[1] == 'stop':
-        return daemon.stop()
-    elif sys.argv[1] == 'restart':
-        return daemon.stop() or daemon.start()
-    else:
-        print 'not an option:', sys.argv[1]
-    return 1
-
-if __name__ == '__main__':
-    sys.exit(main())
diff --git a/tools/xen/xm b/tools/xen/xm
deleted file mode 100755 (executable)
index 09d8036..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/python
-#  -*- mode: python; -*-
-import sys
-from xen.xm import main
-
-main.main(sys.argv)
index f4319be6edac534c1fa0015a58a775f6b3be1ff5..fb90e2c1257a00d82bbd600b70dc2f398a41adfb 100644 (file)
@@ -1,10 +1,16 @@
 
+XEN_ROOT=../..
+include $(XEN_ROOT)/tools/Make.defs
+
 CC       = gcc
 CFLAGS   = -Wall -O3 -Werror
-CFLAGS  += -I../../xen/include/hypervisor-ifs
-CFLAGS  += -I../../linux-xen-sparse/include
-CFLAGS  += -I../xu/lib
-CFLAGS  += -I../lib
+
+CFLAGS  += -I $(XEN_HYPERVISOR_IFS)
+CFLAGS  += -I $(XEN_LINUX_INCLUDE)
+CFLAGS  += -I $(XEN_XC)
+CFLAGS  += -I $(XEN_XU)
+CFLAGS  += -I $(XEN_LIBXC)
+CFLAGS  += -I $(XEN_LIBXUTIL)
 
 HDRS     = $(wildcard *.h)
 OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
@@ -28,4 +34,4 @@ clean:
        $(RM) *.a *.so *.o *.rpm $(BIN)
 
 %: %.c $(HDRS) Makefile
-       $(CC) $(CFLAGS) -o $@ $< -L../xc/lib -lxc
+       $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxc
index 3560745a4272af9a1b8aa981c8bf2d0ed2122774..9972422878d740124040f6ab0dcc6dbfc713220e 100644 (file)
@@ -21,7 +21,7 @@
 #include <argp.h>
 #include <signal.h>
 
-#include "../xc/lib/xc_private.h"
+#include "xc_private.h"
 
 /* from xen/include/hypervisor-ifs */
 #include <trace.h>
diff --git a/tools/xu/Makefile b/tools/xu/Makefile
deleted file mode 100644 (file)
index 6b31fd1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-all:
-       python setup.py build
-
-install: all
-       if [ "$(prefix)" = "" ]; then                   \
-           python setup.py install;                    \
-       elif [ "$(dist)" = "yes" ]; then                \
-           python setup.py install --home="$(prefix)"; \
-       else                                            \
-           python setup.py install --root="$(prefix)"; \
-       fi
-
-clean:
-       rm -rf build *.pyc *.pyo *.a *.so *.o *~ *.rpm 
diff --git a/tools/xu/lib/__init__.py b/tools/xu/lib/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/tools/xu/lib/domain_controller.h b/tools/xu/lib/domain_controller.h
deleted file mode 100644 (file)
index 76dd164..0000000
+++ /dev/null
@@ -1,532 +0,0 @@
-/******************************************************************************
- * domain_controller.h
- * 
- * Interface to server controller (e.g., 'xend'). This header file defines the 
- * interface that is shared with guest OSes.
- * 
- * Copyright (c) 2004, K A Fraser
- */
-
-#ifndef __DOMAIN_CONTROLLER_H__
-#define __DOMAIN_CONTROLLER_H__
-
-
-#ifndef BASIC_START_INFO
-#error "Xen header file hypervisor-if.h must already be included here."
-#endif
-
-
-/*
- * EXTENDED BOOTSTRAP STRUCTURE FOR NEW DOMAINS.
- */
-
-typedef struct {
-    BASIC_START_INFO;
-    u16 domain_controller_evtchn; /* 320 */
-} PACKED extended_start_info_t; /* 322 bytes */
-#define SIF_BLK_BE_DOMAIN (1<<4)  /* Is this a block backend domain? */
-#define SIF_NET_BE_DOMAIN (1<<5)  /* Is this a net backend domain? */
-
-
-/*
- * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
- * interpreted by control software to determine the appropriate action. These 
- * are only really advisories: the controller can actually do as it likes.
- */
-#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
-#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
-#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
-
-
-/*
- * CONTROLLER MESSAGING INTERFACE.
- */
-
-typedef struct {
-    u8 type;     /*  0: echoed in response */
-    u8 subtype;  /*  1: echoed in response */
-    u8 id;       /*  2: echoed in response */
-    u8 length;   /*  3: number of bytes in 'msg' */
-    u8 msg[60];  /*  4: type-specific message data */
-} PACKED control_msg_t; /* 64 bytes */
-
-#define CONTROL_RING_SIZE 8
-typedef u32 CONTROL_RING_IDX;
-#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
-
-typedef struct {
-    control_msg_t tx_ring[CONTROL_RING_SIZE];   /*    0: guest -> controller */
-    control_msg_t rx_ring[CONTROL_RING_SIZE];   /*  512: controller -> guest */
-    CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
-    CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
-} PACKED control_if_t; /* 1040 bytes */
-
-/*
- * Top-level command types.
- */
-#define CMSG_CONSOLE        0  /* Console                 */
-#define CMSG_BLKIF_BE       1  /* Block-device backend    */
-#define CMSG_BLKIF_FE       2  /* Block-device frontend   */
-#define CMSG_NETIF_BE       3  /* Network-device backend  */
-#define CMSG_NETIF_FE       4  /* Network-device frontend */
-#define CMSG_SHUTDOWN       6  /* Shutdown messages       */
-
-
-/******************************************************************************
- * CONSOLE DEFINITIONS
- */
-
-/*
- * Subtypes for console messages.
- */
-#define CMSG_CONSOLE_DATA       0
-
-
-/******************************************************************************
- * BLOCK-INTERFACE FRONTEND DEFINITIONS
- */
-
-/* Messages from domain controller to guest. */
-#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED   0
-
-/* Messages from guest to domain controller. */
-#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
-#define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
-#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
-
-/* These are used by both front-end and back-end drivers. */
-#define blkif_vdev_t   u16
-#define blkif_pdev_t   u16
-#define blkif_sector_t u64
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
- *  Notify a guest about a status change on one of its block interfaces.
- *  If the interface is DESTROYED or DOWN then the interface is disconnected:
- *   1. The shared-memory frame is available for reuse.
- *   2. Any unacknowledged messgaes pending on the interface were dropped.
- */
-#define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
-#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
-#define BLKIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
-typedef struct {
-    u32 handle; /*  0 */
-    u32 status; /*  4 */
-    u16 evtchn; /*  8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
-} PACKED blkif_fe_interface_status_changed_t; /* 10 bytes */
-
-/*
- * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the front-end driver is DOWN or UP.
- *  When the driver goes DOWN then the controller will send no more
- *  status-change notifications. When the driver comes UP then the controller
- *  will send a notification for each interface that currently exists.
- *  If the driver goes DOWN while interfaces are still UP, the domain
- *  will automatically take the interfaces DOWN.
- */
-#define BLKIF_DRIVER_STATUS_DOWN   0
-#define BLKIF_DRIVER_STATUS_UP     1
-typedef struct {
-    /* IN */
-    u32 status;        /*  0: BLKIF_DRIVER_STATUS_??? */
-    /* OUT */
-    /*
-     * Tells driver how many interfaces it should expect to immediately
-     * receive notifications about.
-     */
-    u32 nr_interfaces; /*  4 */
-} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_CONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_CONNECTED message.
- */
-typedef struct {
-    u32      handle;      /*  0 */
-    u32      __pad;
-    memory_t shmem_frame; /*  8 */
-    MEMORY_PADDING;
-} PACKED blkif_fe_interface_connect_t; /* 16 bytes */
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_DISCONNECTED message.
- */
-typedef struct {
-    u32 handle; /*  0 */
-} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
-
-
-/******************************************************************************
- * BLOCK-INTERFACE BACKEND DEFINITIONS
- */
-
-/* Messages from domain controller. */
-#define CMSG_BLKIF_BE_CREATE      0  /* Create a new block-device interface. */
-#define CMSG_BLKIF_BE_DESTROY     1  /* Destroy a block-device interface.    */
-#define CMSG_BLKIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
-#define CMSG_BLKIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
-#define CMSG_BLKIF_BE_VBD_CREATE  4  /* Create a new VBD for an interface.   */
-#define CMSG_BLKIF_BE_VBD_DESTROY 5  /* Delete a VBD from an interface.      */
-#define CMSG_BLKIF_BE_VBD_GROW    6  /* Append an extent to a given VBD.     */
-#define CMSG_BLKIF_BE_VBD_SHRINK  7  /* Remove last extent from a given VBD. */
-
-/* Messages to domain controller. */
-#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
-
-/*
- * Message request/response definitions for block-device messages.
- */
-
-typedef struct {
-    blkif_sector_t sector_start;   /*  0 */
-    blkif_sector_t sector_length;  /*  8 */
-    blkif_pdev_t   device;         /* 16 */
-    u16            __pad;          /* 18 */
-} PACKED blkif_extent_t; /* 20 bytes */
-
-/* Non-specific 'okay' return. */
-#define BLKIF_BE_STATUS_OKAY                0
-/* Non-specific 'error' return. */
-#define BLKIF_BE_STATUS_ERROR               1
-/* The following are specific error returns. */
-#define BLKIF_BE_STATUS_INTERFACE_EXISTS    2
-#define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
-#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
-#define BLKIF_BE_STATUS_VBD_EXISTS          5
-#define BLKIF_BE_STATUS_VBD_NOT_FOUND       6
-#define BLKIF_BE_STATUS_OUT_OF_MEMORY       7
-#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND    8
-#define BLKIF_BE_STATUS_MAPPING_ERROR       9
-
-/* This macro can be used to create an array of descriptive error strings. */
-#define BLKIF_BE_STATUS_ERRORS {    \
-    "Okay",                         \
-    "Non-specific error",           \
-    "Interface already exists",     \
-    "Interface not found",          \
-    "Interface is still connected", \
-    "VBD already exists",           \
-    "VBD not found",                \
-    "Out of memory",                \
-    "Extent not found for VBD",     \
-    "Could not map domain memory" }
-
-/*
- * CMSG_BLKIF_BE_CREATE:
- *  When the driver sends a successful response then the interface is fully
- *  created. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED blkif_be_create_t; /* 12 bytes */
-
-/*
- * CMSG_BLKIF_BE_DESTROY:
- *  When the driver sends a successful response then the interface is fully
- *  torn down. The controller will send a DESTROYED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify interface to be destroyed. */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED blkif_be_destroy_t; /* 12 bytes */
-
-/*
- * CMSG_BLKIF_BE_CONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  connected. The controller will send a CONNECTED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
-    memory_t   shmem_frame;   /*  8: Page cont. shared comms window.     */
-    MEMORY_PADDING;
-    u32        evtchn;        /* 16: Event channel for notifications.    */
-    /* OUT */
-    u32        status;        /* 20 */
-} PACKED blkif_be_connect_t;  /* 24 bytes */
-
-/*
- * CMSG_BLKIF_BE_DISCONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  disconnected. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED blkif_be_disconnect_t; /* 12 bytes */
-
-/* CMSG_BLKIF_BE_VBD_CREATE */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_vdev_t vdevice;     /*  8: Interface-specific id for this VBD. */
-    u16        readonly;      /* 10: Non-zero -> VBD isn't writeable.    */
-    /* OUT */
-    u32        status;        /* 12 */
-} PACKED blkif_be_vbd_create_t; /* 16 bytes */
-
-/* CMSG_BLKIF_BE_VBD_DESTROY */
-typedef struct {
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
-    u16        __pad;         /* 10 */
-    /* OUT */
-    u32        status;        /* 12 */
-} PACKED blkif_be_vbd_destroy_t; /* 16 bytes */
-
-/* CMSG_BLKIF_BE_VBD_GROW */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_extent_t extent;    /*  8: Physical extent to append to VBD.   */
-    blkif_vdev_t vdevice;     /* 28: Interface-specific id of the VBD.   */
-    u16        __pad;         /* 30 */
-    /* OUT */
-    u32        status;        /* 32 */
-} PACKED blkif_be_vbd_grow_t; /* 36 bytes */
-
-/* CMSG_BLKIF_BE_VBD_SHRINK */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
-    u16        __pad;         /* 10 */
-    /* OUT */
-    u32        status;        /* 12 */
-} PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
-
-/*
- * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the back-end driver is DOWN or UP.
- *  If the driver goes DOWN while interfaces are still UP, the controller
- *  will automatically send DOWN notifications.
- */
-typedef struct {
-    u32        status;        /*  0: BLKIF_DRIVER_STATUS_??? */
-} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
-
-
-/******************************************************************************
- * NETWORK-INTERFACE FRONTEND DEFINITIONS
- */
-
-/* Messages from domain controller to guest. */
-#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED   0
-
-/* Messages from guest to domain controller. */
-#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
-#define CMSG_NETIF_FE_INTERFACE_CONNECT         33
-#define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
-
-/*
- * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
- *  Notify a guest about a status change on one of its network interfaces.
- *  If the interface is DESTROYED or DOWN then the interface is disconnected:
- *   1. The shared-memory frame is available for reuse.
- *   2. Any unacknowledged messgaes pending on the interface were dropped.
- */
-#define NETIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
-#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
-#define NETIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
-typedef struct {
-    u32        handle; /*  0 */
-    u32        status; /*  4 */
-    u16        evtchn; /*  8: status == NETIF_INTERFACE_STATUS_CONNECTED */
-    u8         mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
-} PACKED netif_fe_interface_status_changed_t; /* 16 bytes */
-
-/*
- * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the front-end driver is DOWN or UP.
- *  When the driver goes DOWN then the controller will send no more
- *  status-change notifications. When the driver comes UP then the controller
- *  will send a notification for each interface that currently exists.
- *  If the driver goes DOWN while interfaces are still UP, the domain
- *  will automatically take the interfaces DOWN.
- */
-#define NETIF_DRIVER_STATUS_DOWN   0
-#define NETIF_DRIVER_STATUS_UP     1
-typedef struct {
-    /* IN */
-    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
-    /* OUT */
-    /*
-     * Tells driver how many interfaces it should expect to immediately
-     * receive notifications about.
-     */
-    u32        nr_interfaces; /*  4 */
-} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
-
-/*
- * CMSG_NETIF_FE_INTERFACE_CONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_CONNECTED message.
- */
-typedef struct {
-    u32        handle;         /*  0 */
-    u32        __pad;          /*  4 */
-    memory_t   tx_shmem_frame; /*  8 */
-    MEMORY_PADDING;
-    memory_t   rx_shmem_frame; /* 16 */
-    MEMORY_PADDING;
-} PACKED netif_fe_interface_connect_t; /* 24 bytes */
-
-/*
- * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_DISCONNECTED message.
- */
-typedef struct {
-    u32        handle;        /*  0 */
-} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
-
-
-/******************************************************************************
- * NETWORK-INTERFACE BACKEND DEFINITIONS
- */
-
-/* Messages from domain controller. */
-#define CMSG_NETIF_BE_CREATE      0  /* Create a new net-device interface. */
-#define CMSG_NETIF_BE_DESTROY     1  /* Destroy a net-device interface.    */
-#define CMSG_NETIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
-#define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
-
-/* Messages to domain controller. */
-#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
-
-/*
- * Message request/response definitions for net-device messages.
- */
-
-/* Non-specific 'okay' return. */
-#define NETIF_BE_STATUS_OKAY                0
-/* Non-specific 'error' return. */
-#define NETIF_BE_STATUS_ERROR               1
-/* The following are specific error returns. */
-#define NETIF_BE_STATUS_INTERFACE_EXISTS    2
-#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
-#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
-#define NETIF_BE_STATUS_OUT_OF_MEMORY       5
-#define NETIF_BE_STATUS_MAPPING_ERROR       6
-
-/* This macro can be used to create an array of descriptive error strings. */
-#define NETIF_BE_STATUS_ERRORS {    \
-    "Okay",                         \
-    "Non-specific error",           \
-    "Interface already exists",     \
-    "Interface not found",          \
-    "Interface is still connected", \
-    "Out of memory",                \
-    "Could not map domain memory" }
-
-/*
- * CMSG_NETIF_BE_CREATE:
- *  When the driver sends a successful response then the interface is fully
- *  created. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
-    u8         mac[6];        /*  8 */
-    u16        __pad;         /* 14 */
-    /* OUT */
-    u32        status;        /* 16 */
-} PACKED netif_be_create_t; /* 20 bytes */
-
-/*
- * CMSG_NETIF_BE_DESTROY:
- *  When the driver sends a successful response then the interface is fully
- *  torn down. The controller will send a DESTROYED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify interface to be destroyed. */
-    u32        netif_handle;  /*  4: ...ditto...                         */
-    /* OUT */
-    u32   status;             /*  8 */
-} PACKED netif_be_destroy_t; /* 12 bytes */
-
-/*
- * CMSG_NETIF_BE_CONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  connected. The controller will send a CONNECTED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;          /*  0: Domain attached to new interface.   */
-    u32        netif_handle;   /*  4: Domain-specific interface handle.   */
-    memory_t   tx_shmem_frame; /*  8: Page cont. tx shared comms window.  */
-    MEMORY_PADDING;
-    memory_t   rx_shmem_frame; /* 16: Page cont. rx shared comms window.  */
-    MEMORY_PADDING;
-    u16        evtchn;         /* 24: Event channel for notifications.    */
-    u16        __pad;          /* 26 */
-    /* OUT */
-    u32        status;         /* 28 */
-} PACKED netif_be_connect_t; /* 32 bytes */
-
-/*
- * CMSG_NETIF_BE_DISCONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  disconnected. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED netif_be_disconnect_t; /* 12 bytes */
-
-/*
- * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the back-end driver is DOWN or UP.
- *  If the driver goes DOWN while interfaces are still UP, the domain
- *  will automatically send DOWN notifications.
- */
-typedef struct {
-    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
-} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
-
-
-/******************************************************************************
- * SHUTDOWN DEFINITIONS
- */
-
-/*
- * Subtypes for shutdown messages.
- */
-#define CMSG_SHUTDOWN_POWEROFF  0   /* Clean shutdown (SHUTDOWN_poweroff).   */
-#define CMSG_SHUTDOWN_REBOOT    1   /* Clean shutdown (SHUTDOWN_reboot).     */
-#define CMSG_SHUTDOWN_SUSPEND   2   /* Create suspend info, then             */
-                                    /* SHUTDOWN_suspend.                     */
-
-#endif /* __DOMAIN_CONTROLLER_H__ */
diff --git a/tools/xu/lib/xu.c b/tools/xu/lib/xu.c
deleted file mode 100644 (file)
index 48c9759..0000000
+++ /dev/null
@@ -1,1386 +0,0 @@
-/******************************************************************************
- * utils.c
- * 
- * Copyright (c) 2004, K A Fraser
- */
-
-#include <Python.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/mman.h>
-#include <sys/poll.h>
-#include <netinet/in.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <xc.h>
-
-#include <hypervisor-if.h>
-#include "domain_controller.h"
-
-#include <asm-xen/proc_cmd.h>
-
-#define XENPKG "xen.ext.xu"
-
-/* Needed for Python versions earlier than 2.3. */
-#ifndef PyMODINIT_FUNC
-#define PyMODINIT_FUNC DL_EXPORT(void)
-#endif
-
-/* NB. The following should be kept in sync with the kernel's evtchn driver. */
-#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
-#define EVTCHN_DEV_MAJOR 10
-#define EVTCHN_DEV_MINOR 200
-#define PORT_NORMAL     0x0000   /* A standard event notification.      */ 
-#define PORT_EXCEPTION  0x8000   /* An exceptional notification.        */
-#define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
-/* /dev/xen/evtchn ioctls: */
-/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
-#define EVTCHN_RESET  _IO('E', 1)
-/* EVTCHN_BIND: Bind to teh specified event-channel port. */
-#define EVTCHN_BIND   _IO('E', 2)
-/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
-#define EVTCHN_UNBIND _IO('E', 3)
-
-/* Size of a machine page frame. */
-#define PAGE_SIZE 4096
-
-
-/*
- * *********************** NOTIFIER ***********************
- */
-
-typedef struct {
-    PyObject_HEAD;
-    int evtchn_fd;
-} xu_notifier_object;
-
-static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    u16 v;
-    int bytes;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-    
-    while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
-    {
-        if ( errno == EINTR )
-            continue;
-        if ( errno == EAGAIN )
-            goto none;
-        return PyErr_SetFromErrno(PyExc_IOError);
-    }
-    
-    if ( bytes == sizeof(v) )
-        return Py_BuildValue("(i,i)", v&PORTIDX_MASK, v&~PORTIDX_MASK);
-
- none:
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    u16 v;
-    int idx;
-
-    if ( !PyArg_ParseTuple(args, "i", &idx) )
-        return NULL;
-
-    v = (u16)idx;
-    
-    (void)write(xun->evtchn_fd, &v, sizeof(v));
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    int idx;
-
-    if ( !PyArg_ParseTuple(args, "i", &idx) )
-        return NULL;
-
-    if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
-        return PyErr_SetFromErrno(PyExc_IOError);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    int idx;
-
-    if ( !PyArg_ParseTuple(args, "i", &idx) )
-        return NULL;
-
-    if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
-        return PyErr_SetFromErrno(PyExc_IOError);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    return PyInt_FromLong(xun->evtchn_fd);
-}
-
-static PyMethodDef xu_notifier_methods[] = {
-    { "read",
-      (PyCFunction)xu_notifier_read,
-      METH_VARARGS,
-      "Read a (@port, @type) pair.\n" },
-
-    { "unmask", 
-      (PyCFunction)xu_notifier_unmask,
-      METH_VARARGS,
-      "Unmask notifications for a @port.\n" },
-
-    { "bind", 
-      (PyCFunction)xu_notifier_bind,
-      METH_VARARGS,
-      "Get notifications for a @port.\n" },
-
-    { "unbind", 
-      (PyCFunction)xu_notifier_unbind,
-      METH_VARARGS,
-      "No longer get notifications for a @port.\n" },
-
-    { "fileno", 
-      (PyCFunction)xu_notifier_fileno,
-      METH_VARARGS,
-      "Return the file descriptor for the notification channel.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_notifier_type;
-
-static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
-{
-    xu_notifier_object *xun;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
-
- reopen:
-    xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
-    if ( xun->evtchn_fd == -1 )
-    {
-        if ( (errno == ENOENT) &&
-             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
-             (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, 
-                    (EVTCHN_DEV_MAJOR << 8) | EVTCHN_DEV_MINOR) == 0) )
-            goto reopen;
-        PyObject_Del((PyObject *)xun);
-        return PyErr_SetFromErrno(PyExc_IOError);
-    }
-
-    return (PyObject *)xun;
-}
-
-static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
-{
-    if ( strcmp(name, "EXCEPTION") == 0 )
-        return PyInt_FromLong(PORT_EXCEPTION);
-    if ( strcmp(name, "NORMAL") == 0 )
-        return PyInt_FromLong(PORT_NORMAL);
-    return Py_FindMethod(xu_notifier_methods, obj, name);
-}
-
-static void xu_notifier_dealloc(PyObject *self)
-{
-    xu_notifier_object *xun = (xu_notifier_object *)self;
-    (void)close(xun->evtchn_fd);
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_notifier_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "notifier",
-    sizeof(xu_notifier_object),
-    0,
-    xu_notifier_dealloc, /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_notifier_getattr, /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** MESSAGE ***********************
- */
-
-#define TYPE(_x,_y) (((_x)<<8)|(_y))
-#define P2C(_struct, _field, _ctype)                                      \
-    do {                                                                  \
-        PyObject *obj;                                                    \
-        if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL )     \
-        {                                                                 \
-            if ( PyInt_Check(obj) )                                       \
-            {                                                             \
-                ((_struct *)&xum->msg.msg[0])->_field =                   \
-                  (_ctype)PyInt_AsLong(obj);                              \
-                dict_items_parsed++;                                      \
-            }                                                             \
-            else if ( PyLong_Check(obj) )                                 \
-            {                                                             \
-                ((_struct *)&xum->msg.msg[0])->_field =                   \
-                  (_ctype)PyLong_AsUnsignedLongLong(obj);                 \
-                dict_items_parsed++;                                      \
-            }                                                             \
-        }                                                                 \
-        xum->msg.length = sizeof(_struct);                                \
-    } while ( 0 )
-#define C2P(_struct, _field, _pytype, _ctype)                             \
-    do {                                                                  \
-        PyObject *obj = Py ## _pytype ## _From ## _ctype                  \
-                        (((_struct *)&xum->msg.msg[0])->_field);          \
-        if ( dict == NULL ) dict = PyDict_New();                          \
-        PyDict_SetItemString(dict, #_field, obj);                         \
-    } while ( 0 )
-
-typedef struct {
-    PyObject_HEAD;
-    control_msg_t msg;
-} xu_message_object;
-
-static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-    char *str;
-    int len;
-
-    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
-        return NULL;
-
-    if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
-    {
-        PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
-        return NULL;
-    }
-
-    memcpy(&xum->msg.msg[xum->msg.length], str, len);
-    xum->msg.length += len;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-    PyObject *payload;
-    int dict_items_parsed = 0;
-
-    if ( !PyArg_ParseTuple(args, "O", &payload) )
-        return NULL;
-
-    if ( !PyDict_Check(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
-        return NULL;
-    }
-
-    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
-    {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(blkif_fe_driver_status_changed_t, nr_interfaces, u32);
-        break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
-        break;
-    }
-
-    if ( dict_items_parsed != PyDict_Size(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
-        return NULL;
-    }
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-    PyObject *dict = NULL;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    switch ( TYPE(xum->msg.type, xum->msg.subtype) )
-    {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
-        C2P(blkif_fe_interface_status_changed_t, handle, Int, Long);
-        C2P(blkif_fe_interface_status_changed_t, status, Int, Long);
-        C2P(blkif_fe_interface_status_changed_t, evtchn, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
-        C2P(blkif_fe_driver_status_changed_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
-        C2P(blkif_fe_interface_connect_t, handle,      Int, Long);
-        C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
-        C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
-        C2P(blkif_be_create_t, domid,        Int, Long);
-        C2P(blkif_be_create_t, blkif_handle, Int, Long);
-        C2P(blkif_be_create_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
-        C2P(blkif_be_destroy_t, domid,        Int, Long);
-        C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
-        C2P(blkif_be_destroy_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
-        C2P(blkif_be_connect_t, domid,        Int, Long);
-        C2P(blkif_be_connect_t, blkif_handle, Int, Long);
-        C2P(blkif_be_connect_t, shmem_frame,  Int, Long);
-        C2P(blkif_be_connect_t, evtchn,       Int, Long);
-        C2P(blkif_be_connect_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
-        C2P(blkif_be_disconnect_t, domid,        Int, Long);
-        C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
-        C2P(blkif_be_disconnect_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
-        C2P(blkif_be_vbd_create_t, domid,        Int, Long);
-        C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
-        C2P(blkif_be_vbd_create_t, vdevice,      Int, Long);
-        C2P(blkif_be_vbd_create_t, readonly,     Int, Long);
-        C2P(blkif_be_vbd_create_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
-        C2P(blkif_be_vbd_destroy_t, domid,        Int, Long);
-        C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
-        C2P(blkif_be_vbd_destroy_t, vdevice,      Int, Long);
-        C2P(blkif_be_vbd_destroy_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
-        C2P(blkif_be_vbd_grow_t, domid,         Int, Long);
-        C2P(blkif_be_vbd_grow_t, blkif_handle,  Int, Long);
-        C2P(blkif_be_vbd_grow_t, vdevice,       Int, Long);
-        C2P(blkif_be_vbd_grow_t, extent.sector_start, 
-             Long, UnsignedLongLong);
-        C2P(blkif_be_vbd_grow_t, extent.sector_length, 
-             Long, UnsignedLongLong);
-        C2P(blkif_be_vbd_grow_t, extent.device, Int, Long);
-        C2P(blkif_be_vbd_grow_t, status,        Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
-        C2P(blkif_be_vbd_shrink_t, domid,        Int, Long);
-        C2P(blkif_be_vbd_shrink_t, blkif_handle, Int, Long);
-        C2P(blkif_be_vbd_shrink_t, vdevice,      Int, Long);
-        C2P(blkif_be_vbd_shrink_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED):
-        C2P(blkif_be_driver_status_changed_t, status, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
-        C2P(netif_fe_interface_status_changed_t, handle, Int, Long);
-        C2P(netif_fe_interface_status_changed_t, status, Int, Long);
-        C2P(netif_fe_interface_status_changed_t, evtchn, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        C2P(netif_fe_driver_status_changed_t, status,        Int, Long);
-        C2P(netif_fe_driver_status_changed_t, nr_interfaces, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
-        C2P(netif_fe_interface_connect_t, handle,         Int, Long);
-        C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
-        C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
-        C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
-        C2P(netif_be_create_t, domid,        Int, Long);
-        C2P(netif_be_create_t, netif_handle, Int, Long);
-        C2P(netif_be_create_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
-        C2P(netif_be_destroy_t, domid,        Int, Long);
-        C2P(netif_be_destroy_t, netif_handle, Int, Long);
-        C2P(netif_be_destroy_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
-        C2P(netif_be_connect_t, domid,          Int, Long);
-        C2P(netif_be_connect_t, netif_handle,   Int, Long);
-        C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
-        C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
-        C2P(netif_be_connect_t, evtchn,         Int, Long);
-        C2P(netif_be_connect_t, status,         Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
-        C2P(netif_be_disconnect_t, domid,        Int, Long);
-        C2P(netif_be_disconnect_t, netif_handle, Int, Long);
-        C2P(netif_be_disconnect_t, status,       Int, Long);
-        return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED):
-        C2P(netif_be_driver_status_changed_t, status, Int, Long);
-        return dict;
-    }
-
-    return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
-}
-
-static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum = (xu_message_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    return Py_BuildValue("{s:i,s:i,s:i}",
-                         "type",    xum->msg.type,
-                         "subtype", xum->msg.subtype,
-                         "id",      xum->msg.id);
-}
-
-static PyMethodDef xu_message_methods[] = {
-    { "append_payload", 
-      (PyCFunction)xu_message_append_payload,
-      METH_VARARGS,
-      "Append @str to the message payload.\n" },
-
-    { "set_response_fields",
-      (PyCFunction)xu_message_set_response_fields,
-      METH_VARARGS,
-      "Fill in the response fields in a message that was passed to us.\n" },
-
-    { "get_payload",
-      (PyCFunction)xu_message_get_payload,
-      METH_VARARGS,
-      "Return the message payload in string form.\n" },
-
-    { "get_header",
-      (PyCFunction)xu_message_get_header,
-      METH_VARARGS,
-      "Returns a dictionary of values for @type, @subtype, and @id.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_message_type;
-
-static PyObject *xu_message_new(PyObject *self, PyObject *args)
-{
-    xu_message_object *xum;
-    int type, subtype, id, dict_items_parsed = 0;
-    PyObject *payload = NULL;
-
-    if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
-        return NULL;
-
-    xum = PyObject_New(xu_message_object, &xu_message_type);
-
-    xum->msg.type    = type;
-    xum->msg.subtype = subtype;
-    xum->msg.id      = id;
-    xum->msg.length  = 0;
-
-    if ( payload == NULL )
-        return (PyObject *)xum;
-
-    if ( !PyDict_Check(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
-        PyObject_Del((PyObject *)xum);
-        return NULL;
-    }
-
-    switch ( TYPE(type, subtype) )
-    {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
-        P2C(blkif_fe_interface_status_changed_t, handle, u32);
-        P2C(blkif_fe_interface_status_changed_t, status, u32);
-        P2C(blkif_fe_interface_status_changed_t, evtchn, u16);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
-        P2C(blkif_be_create_t, domid,        u32);
-        P2C(blkif_be_create_t, blkif_handle, u32);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
-        P2C(blkif_be_destroy_t, domid,        u32);
-        P2C(blkif_be_destroy_t, blkif_handle, u32);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
-        P2C(blkif_be_connect_t, domid,        u32);
-        P2C(blkif_be_connect_t, blkif_handle, u32);
-        P2C(blkif_be_connect_t, shmem_frame,  memory_t);
-        P2C(blkif_be_connect_t, evtchn,       u16);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
-        P2C(blkif_be_disconnect_t, domid,        u32);
-        P2C(blkif_be_disconnect_t, blkif_handle, u32);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
-        P2C(blkif_be_vbd_create_t, domid,        u32);
-        P2C(blkif_be_vbd_create_t, blkif_handle, u32);
-        P2C(blkif_be_vbd_create_t, vdevice,      blkif_vdev_t);
-        P2C(blkif_be_vbd_create_t, readonly,     u16);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
-        P2C(blkif_be_vbd_destroy_t, domid,        u32);
-        P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
-        P2C(blkif_be_vbd_destroy_t, vdevice,      blkif_vdev_t);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
-        P2C(blkif_be_vbd_grow_t, domid,                u32);
-        P2C(blkif_be_vbd_grow_t, blkif_handle,         u32);
-        P2C(blkif_be_vbd_grow_t, vdevice,              blkif_vdev_t);
-        P2C(blkif_be_vbd_grow_t, extent.sector_start,  blkif_sector_t);
-        P2C(blkif_be_vbd_grow_t, extent.sector_length, blkif_sector_t);
-        P2C(blkif_be_vbd_grow_t, extent.device,        blkif_pdev_t);
-        break;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
-        P2C(blkif_be_vbd_shrink_t, domid,        u32);
-        P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
-        P2C(blkif_be_vbd_shrink_t, vdevice,      blkif_vdev_t);
-        break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
-        P2C(netif_fe_interface_status_changed_t, handle, u32);
-        P2C(netif_fe_interface_status_changed_t, status, u32);
-        P2C(netif_fe_interface_status_changed_t, evtchn, u16);
-        P2C(netif_fe_interface_status_changed_t, mac[0], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[1], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[2], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[3], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[4], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[5], u8);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
-        P2C(netif_be_create_t, domid,        u32);
-        P2C(netif_be_create_t, netif_handle, u32);
-        P2C(netif_be_create_t, mac[0],       u8);
-        P2C(netif_be_create_t, mac[1],       u8);
-        P2C(netif_be_create_t, mac[2],       u8);
-        P2C(netif_be_create_t, mac[3],       u8);
-        P2C(netif_be_create_t, mac[4],       u8);
-        P2C(netif_be_create_t, mac[5],       u8);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
-        P2C(netif_be_destroy_t, domid,        u32);
-        P2C(netif_be_destroy_t, netif_handle, u32);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
-        P2C(netif_be_connect_t, domid,          u32);
-        P2C(netif_be_connect_t, netif_handle,   u32);
-        P2C(netif_be_connect_t, tx_shmem_frame, memory_t);
-        P2C(netif_be_connect_t, rx_shmem_frame, memory_t);
-        P2C(netif_be_connect_t, evtchn,         u16);
-        break;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
-        P2C(netif_be_disconnect_t, domid,        u32);
-        P2C(netif_be_disconnect_t, netif_handle, u32);
-        break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(netif_fe_driver_status_changed_t, status,        u32);
-        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
-        break;
-    }
-
-    if ( dict_items_parsed != PyDict_Size(payload) )
-    {
-        PyErr_SetString(PyExc_TypeError, "payload contains bad items");
-        PyObject_Del((PyObject *)xum);
-        return NULL;
-    }
-
-    return (PyObject *)xum;
-}
-
-static PyObject *xu_message_getattr(PyObject *obj, char *name)
-{
-    xu_message_object *xum;
-    if ( strcmp(name, "MAX_PAYLOAD") == 0 )
-        return PyInt_FromLong(sizeof(xum->msg.msg));
-    return Py_FindMethod(xu_message_methods, obj, name);
-}
-
-static void xu_message_dealloc(PyObject *self)
-{
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_message_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "message",
-    sizeof(xu_message_object),
-    0,
-    xu_message_dealloc,   /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_message_getattr,   /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** PORT ***********************
- */
-
-static control_if_t *map_control_interface(int fd, unsigned long pfn)
-{
-    char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
-                       MAP_SHARED, fd, pfn * PAGE_SIZE);
-    if ( vaddr == MAP_FAILED )
-        return NULL;
-    return (control_if_t *)(vaddr + 2048);
-}
-static void unmap_control_interface(int fd, control_if_t *c)
-{
-    char *vaddr = (char *)c - 2048;
-    (void)munmap(vaddr, PAGE_SIZE);
-}
-
-typedef struct xu_port_object {
-    PyObject_HEAD;
-    int mem_fd;
-    int xc_handle;
-    u32 remote_dom;
-    int local_port, remote_port;
-    control_if_t    *interface;
-    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
-    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
-} xu_port_object;
-
-static PyObject *port_error;
-
-static int xup_connect(xu_port_object *xup, domid_t dom,
-                       int local_port, int remote_port){
-    // From our prespective rx = producer, tx = consumer.
-    int err = 0;
-    printf("%s> dom=%u %d:%d\n", __FUNCTION__, (unsigned int)dom, 
-           local_port, remote_port);
-
-    // Consumer = tx.
-    //xup->interface->tx_resp_prod = 0;
-    //xup->interface->tx_req_prod = 0;
-    xup->tx_resp_prod = xup->interface->tx_resp_prod;
-    xup->tx_req_cons = xup->interface->tx_resp_prod;
-    printf("%s> tx: %u %u : %u %u\n", __FUNCTION__,
-           (unsigned int)xup->interface->tx_resp_prod,
-           (unsigned int)xup->tx_resp_prod,
-           (unsigned int)xup->tx_req_cons,
-           (unsigned int)xup->interface->tx_req_prod);
-
-    // Producer = rx.
-    //xup->interface->rx_req_prod  = 0;
-    //xup->interface->rx_resp_prod = 0;
-    xup->rx_req_prod  = xup->interface->rx_req_prod;
-    xup->rx_resp_cons = xup->interface->rx_resp_prod;
-    printf("%s> rx: %u %u : %u %u\n", __FUNCTION__,
-           (unsigned int)xup->rx_resp_cons,
-           (unsigned int)xup->interface->rx_resp_prod,
-           (unsigned int)xup->interface->rx_req_prod,
-           (unsigned int)xup->rx_req_prod);
-
-    xup->remote_dom   = dom;
-    xup->local_port   = local_port;
-    xup->remote_port  = remote_port;
-
-    printf("%s< err=%d\n", __FUNCTION__, err);
-    return err;
-}
-
-static PyObject *xu_port_notify(PyObject *self, PyObject *args)
-{
-    xu_port_object *xup = (xu_port_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    CONTROL_RING_IDX   c = xup->tx_req_cons;
-    control_if_t      *cif = xup->interface;
-    control_msg_t     *cmsg;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (c == cif->tx_req_prod) || 
-         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
-    {
-        PyErr_SetString(port_error, "no request to read");
-        return NULL;
-    }
-
-    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
-    xum = PyObject_New(xu_message_object, &xu_message_type);
-    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
-    if ( xum->msg.length > sizeof(xum->msg.msg) )
-        xum->msg.length = sizeof(xum->msg.msg);
-    xup->tx_req_cons++;
-    return (PyObject *)xum;
-}
-
-static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    CONTROL_RING_IDX   p = xup->rx_req_prod;
-    control_if_t      *cif = xup->interface;
-    control_msg_t     *cmsg;
-
-    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
-        return NULL;
-
-    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
-    {
-        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
-        return NULL;        
-    }
-
-    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
-    {
-        PyErr_SetString(port_error, "no space to write request");
-        return NULL;
-    }
-
-    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
-    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
-
-    xup->rx_req_prod = cif->rx_req_prod = p + 1;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    CONTROL_RING_IDX   c = xup->rx_resp_cons;
-    control_if_t      *cif = xup->interface;
-    control_msg_t     *cmsg;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
-    {
-        PyErr_SetString(port_error, "no response to read");
-        return NULL;
-    }
-
-    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
-    xum = PyObject_New(xu_message_object, &xu_message_type);
-    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
-    if ( xum->msg.length > sizeof(xum->msg.msg) )
-        xum->msg.length = sizeof(xum->msg.msg);
-    xup->rx_resp_cons++;
-    return (PyObject *)xum;
-}
-
-static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    xu_message_object *xum;
-    CONTROL_RING_IDX   p = xup->tx_resp_prod;
-    control_if_t      *cif = xup->interface;
-    control_msg_t     *cmsg;
-
-    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
-        return NULL;
-
-    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
-    {
-        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
-        return NULL;        
-    }
-
-    if ( p == xup->tx_req_cons )
-    {
-        PyErr_SetString(port_error, "no space to write response");
-        return NULL;
-    }
-
-    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
-    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
-
-    xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    CONTROL_RING_IDX   c = xup->tx_req_cons;
-    control_if_t      *cif = xup->interface;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (c == cif->tx_req_prod) || 
-         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
-        return PyInt_FromLong(0);
-
-    return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    CONTROL_RING_IDX   p = xup->rx_req_prod;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
-        return PyInt_FromLong(0);
-
-    return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    CONTROL_RING_IDX   c = xup->rx_resp_cons;
-    control_if_t      *cif = xup->interface;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
-        return PyInt_FromLong(0);
-
-    return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_space_to_write_response(
-    PyObject *self, PyObject *args)
-{
-    xu_port_object    *xup = (xu_port_object *)self;
-    CONTROL_RING_IDX   p = xup->tx_resp_prod;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( p == xup->tx_req_cons )
-        return PyInt_FromLong(0);
-
-    return PyInt_FromLong(1);
-}
-
-static PyMethodDef xu_port_methods[] = {
-    { "notify",
-      (PyCFunction)xu_port_notify,
-      METH_VARARGS,
-      "Send a notification to the remote end.\n" },
-
-    { "read_request",
-      (PyCFunction)xu_port_read_request,
-      METH_VARARGS,
-      "Read a request message from the control interface.\n" },
-
-    { "write_request",
-      (PyCFunction)xu_port_write_request,
-      METH_VARARGS,
-      "Write a request message to the control interface.\n" },
-
-    { "read_response",
-      (PyCFunction)xu_port_read_response,
-      METH_VARARGS,
-      "Read a response message from the control interface.\n" },
-
-    { "write_response",
-      (PyCFunction)xu_port_write_response,
-      METH_VARARGS,
-      "Write a response message to the control interface.\n" },
-
-    { "request_to_read",
-      (PyCFunction)xu_port_request_to_read,
-      METH_VARARGS,
-      "Returns TRUE if there is a request message to read.\n" },
-
-    { "space_to_write_request",
-      (PyCFunction)xu_port_space_to_write_request,
-      METH_VARARGS,
-      "Returns TRUE if there is space to write a request message.\n" },
-
-    { "response_to_read",
-      (PyCFunction)xu_port_response_to_read,
-      METH_VARARGS,
-      "Returns TRUE if there is a response message to read.\n" },
-
-    { "space_to_write_response",
-      (PyCFunction)xu_port_space_to_write_response,
-      METH_VARARGS,
-      "Returns TRUE if there is space to write a response message.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_port_type;
-
-static PyObject *xu_port_new(PyObject *self, PyObject *args)
-{
-    xu_port_object *xup;
-    u32 dom;
-    int port1, port2;
-    xc_dominfo_t info;
-
-    if ( !PyArg_ParseTuple(args, "i", &dom) )
-        return NULL;
-
-    xup = PyObject_New(xu_port_object, &xu_port_type);
-
-    if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 )
-    {
-        PyErr_SetString(port_error, "Could not open '/dev/mem'");
-        goto fail1;
-    }
-
-    /* Set the General-Purpose Subject whose page frame will be mapped. */
-    (void)ioctl(xup->mem_fd, _IO('M', 1), (unsigned long)dom);
-
-    if ( (xup->xc_handle = xc_interface_open()) == -1 )
-    {
-        PyErr_SetString(port_error, "Could not open Xen control interface");
-        goto fail2;
-    }
-
-    if ( dom == 0 )
-    {
-        /*
-         * The control-interface event channel for DOM0 is already set up.
-         * We use an ioctl to discover the port at our end of the channel.
-         */
-        port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
-        port2 = -1; /* We don't need the remote end of the DOM0 link. */
-        if ( port1 < 0 )
-        {
-            PyErr_SetString(port_error, "Could not open channel to DOM0");
-            goto fail3;
-        }
-    }
-    else if ( xc_evtchn_bind_interdomain(xup->xc_handle, 
-                                         DOMID_SELF, dom, 
-                                         &port1, &port2) != 0 )
-    {
-        PyErr_SetString(port_error, "Could not open channel to domain");
-        goto fail3;
-    }
-
-    if ( (xc_domain_getinfo(xup->xc_handle, dom, 1, &info) != 1) ||
-         (info.domid != dom) )
-    {
-        PyErr_SetString(port_error, "Failed to obtain domain status");
-        goto fail4;
-    }
-
-    xup->interface = 
-        map_control_interface(xup->mem_fd, info.shared_info_frame);
-    if ( xup->interface == NULL )
-    {
-        PyErr_SetString(port_error, "Failed to map domain control interface");
-        goto fail4;
-    }
-
-    xup_connect(xup, dom, port1, port2);
-    return (PyObject *)xup;
-
-    
- fail4:
-    (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
- fail3:
-    (void)xc_interface_close(xup->xc_handle);
- fail2:
-    (void)close(xup->mem_fd);
- fail1:
-    PyObject_Del((PyObject *)xup);
-    return NULL;        
-}
-
-static PyObject *xu_port_getattr(PyObject *obj, char *name)
-{
-    xu_port_object *xup = (xu_port_object *)obj;
-    if ( strcmp(name, "local_port") == 0 )
-        return PyInt_FromLong(xup->local_port);
-    if ( strcmp(name, "remote_port") == 0 )
-        return PyInt_FromLong(xup->remote_port);
-    if ( strcmp(name, "remote_dom") == 0 )
-        return PyInt_FromLong(xup->remote_dom);
-    return Py_FindMethod(xu_port_methods, obj, name);
-}
-
-static void xu_port_dealloc(PyObject *self)
-{
-    xu_port_object *xup = (xu_port_object *)self;
-    unmap_control_interface(xup->mem_fd, xup->interface);
-    if ( xup->remote_dom != 0 )
-        (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
-    (void)xc_interface_close(xup->xc_handle);
-    (void)close(xup->mem_fd);
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_port_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "port",
-    sizeof(xu_port_object),
-    0,
-    xu_port_dealloc,     /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_port_getattr,     /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** BUFFER ***********************
- */
-
-#define BUFSZ 65536
-#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
-typedef unsigned int BUF_IDX;
-
-typedef struct {
-    PyObject_HEAD;
-    char        *buf;
-    unsigned int prod, cons;
-} xu_buffer_object;
-
-static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
-{
-    PyObject *str1, *str2;
-    int len1, len2, c = MASK_BUF_IDX(xub->cons);
-
-    len1 = xub->prod - xub->cons;
-    if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
-        len1 = BUFSZ - c;
-    if ( len1 > max )         /* clip to specified maximum */
-        len1 = max;
-    if ( len1 < 0 )           /* sanity */
-        len1 = 0;
-
-    if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
-        return NULL;
-
-    if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
-    {
-        len2 = max - len1;
-        if ( len2 > MASK_BUF_IDX(xub->prod) )
-            len2 = MASK_BUF_IDX(xub->prod);
-        if ( len2 > 0 )
-        {
-            str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
-            if ( str2 == NULL )
-                return NULL;
-            PyString_ConcatAndDel(&str1, str2);
-            if ( str1 == NULL )
-                return NULL;
-        }
-    }
-
-    return str1;
-}
-
-static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    int max = 1024;
-
-    if ( !PyArg_ParseTuple(args, "|i", &max) )
-        return NULL;
-    
-    return __xu_buffer_peek(xub, max);
-}
-
-static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    PyObject *str;
-    int max = 1024;
-
-    if ( !PyArg_ParseTuple(args, "|i", &max) )
-        return NULL;
-
-    if ( (str = __xu_buffer_peek(xub, max)) != NULL )
-        xub->cons += PyString_Size(str);
-
-    return str;
-}
-
-static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    int max, len;
-
-    if ( !PyArg_ParseTuple(args, "i", &max) )
-        return NULL;
-
-    len = xub->prod - xub->cons;
-    if ( len > max )
-        len = max;
-    if ( len < 0 )
-        len = 0;
-
-    xub->cons += len;
-
-    return PyInt_FromLong(len);
-}
-
-static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    char *str;
-    int len, len1, len2;
-
-    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
-        return NULL;
-
-    len1 = len;
-    if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
-        len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
-    if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
-        len1 = BUFSZ - (xub->prod - xub->cons);
-
-    if ( len1 == 0 )
-        return PyInt_FromLong(0);
-
-    memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
-    xub->prod += len1;
-
-    if ( len1 < len )
-    {
-        len2 = len - len1;
-        if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
-            len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
-        if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
-            len2 = BUFSZ - (xub->prod - xub->cons);
-        if ( len2 != 0 )
-        {
-            memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
-            xub->prod += len2;
-            return PyInt_FromLong(len1 + len2);
-        }
-    }
-
-    return PyInt_FromLong(len1);
-}
-
-static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( xub->cons == xub->prod )
-        return PyInt_FromLong(1);
-
-    return PyInt_FromLong(0);
-}
-
-static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    if ( (xub->prod - xub->cons) == BUFSZ )
-        return PyInt_FromLong(1);
-
-    return PyInt_FromLong(0);
-}
-
-static PyMethodDef xu_buffer_methods[] = {
-    { "peek", 
-      (PyCFunction)xu_buffer_peek,
-      METH_VARARGS,
-      "Peek up to @max bytes from the buffer. Returns a string.\n" },
-
-    { "read", 
-      (PyCFunction)xu_buffer_read,
-      METH_VARARGS,
-      "Read up to @max bytes from the buffer. Returns a string.\n" },
-
-    { "discard", 
-      (PyCFunction)xu_buffer_discard,
-      METH_VARARGS,
-      "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
-
-    { "write", 
-      (PyCFunction)xu_buffer_write,
-      METH_VARARGS,
-      "Write @string into buffer. Return number of bytes written.\n" },
-
-    { "empty", 
-      (PyCFunction)xu_buffer_empty,
-      METH_VARARGS,
-      "Return TRUE if the buffer is empty.\n" },
-
-    { "full", 
-      (PyCFunction)xu_buffer_full,
-      METH_VARARGS,
-      "Return TRUE if the buffer is full.\n" },
-
-    { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_buffer_type;
-
-static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
-{
-    xu_buffer_object *xub;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
-
-    if ( (xub->buf = malloc(BUFSZ)) == NULL )
-    {
-        PyObject_Del((PyObject *)xub);
-        return NULL;
-    }
-
-    xub->prod = xub->cons = 0;
-
-    return (PyObject *)xub;
-}
-
-static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
-{
-    return Py_FindMethod(xu_buffer_methods, obj, name);
-}
-
-static void xu_buffer_dealloc(PyObject *self)
-{
-    xu_buffer_object *xub = (xu_buffer_object *)self;
-    free(xub->buf);
-    PyObject_Del(self);
-}
-
-static PyTypeObject xu_buffer_type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,
-    "buffer",
-    sizeof(xu_buffer_object),
-    0,
-    xu_buffer_dealloc,   /* tp_dealloc     */
-    NULL,                /* tp_print       */
-    xu_buffer_getattr,   /* tp_getattr     */
-    NULL,                /* tp_setattr     */
-    NULL,                /* tp_compare     */
-    NULL,                /* tp_repr        */
-    NULL,                /* tp_as_number   */
-    NULL,                /* tp_as_sequence */
-    NULL,                /* tp_as_mapping  */
-    NULL                 /* tp_hash        */
-};
-
-
-
-/*
- * *********************** MODULE WRAPPER ***********************
- */
-
-static void handle_child_death(int dummy)
-{
-    while ( waitpid(-1, NULL, WNOHANG) > 0 )
-        continue;
-}
-
-static PyObject *xu_autoreap(PyObject *self, PyObject *args)
-{
-    struct sigaction sa;
-
-    if ( !PyArg_ParseTuple(args, "") )
-        return NULL;
-
-    memset(&sa, 0, sizeof(sa));
-    sa.sa_handler = handle_child_death;
-    sigemptyset(&sa.sa_mask);
-    sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
-    (void)sigaction(SIGCHLD, &sa, NULL);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyMethodDef xu_methods[] = {
-    { "notifier", xu_notifier_new, METH_VARARGS, 
-      "Create a new notifier." },
-    { "message", xu_message_new, METH_VARARGS, 
-      "Create a new communications message." },
-    { "port", xu_port_new, METH_VARARGS, 
-      "Create a new communications port." },
-    { "buffer", xu_buffer_new, METH_VARARGS, 
-      "Create a new ring buffer." },
-    { "autoreap", xu_autoreap, METH_VARARGS,
-      "Ensure that zombie children are automatically reaped by the OS." },
-    { NULL, NULL, 0, NULL }
-};
-
-PyMODINIT_FUNC initxu(void)
-{
-    PyObject *m, *d;
-
-    m = Py_InitModule(XENPKG, xu_methods);
-
-    d = PyModule_GetDict(m);
-    port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
-    PyDict_SetItemString(d, "PortError", port_error);
-}
diff --git a/tools/xu/setup.py b/tools/xu/setup.py
deleted file mode 100644 (file)
index e342c78..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-
-from distutils.core import setup, Extension
-
-xu = Extension("xu",
-                  extra_compile_args   = ["-fno-strict-aliasing"],
-                  include_dirs         = ["../xc/lib",
-                                          "../../xen/include/hypervisor-ifs",
-                                          "../../linux-xen-sparse/include"],
-                  library_dirs         = ["../xc/lib"],
-                  libraries            = ["xc"],
-                  sources              = ["lib/xu.c"])
-
-setup(name = "xu",
-      version = "1.0",
-      #packages = ["xend"],
-      #package_dir = { "xend" : "lib" },
-      ext_package = "xen.ext",
-      ext_modules = [ xu ]
-      )